Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Should I explicitly separate "import" and "import type" statements? #39861

Closed
parzhitsky opened this issue Aug 1, 2020 · 9 comments
Closed
Labels
Question An issue which isn't directly actionable in code

Comments

@parzhitsky
Copy link

parzhitsky commented Aug 1, 2020

A.S.: This is an opinion-based question, I cannot ask such on StackOverflow

I've been using the import type statement for a while now, and I wonder, what was the intended use-case for it:

  • Is it a separate TypeScript-exclusive fully-fledged feature, i.e. "import for types"? Or
  • is it an extension to regular import, designed to be used in the case when only type information is actually used, i.e. fallback?

I always thought of import type as "import for types", the first option, so the code always looked like this:

  import type { Type } from "some-module";
+ import { value } from "some-module";

… but auto-import in VSCode suggests it is actually the second, fallback-ish:

- import type { Type } from "some-module";
+ import { Type, value } from "some-module";

Now, I understand that both will work correctly, and it is basically a matter of stylistic choice for the team, but the authors' original intention is important for me, and I'm a sole developer in this case

@iraj465
Copy link

iraj465 commented Aug 2, 2020

Ideally one goes for -
import { Type, value } from "some-module";
import type { Type } from "some-module"; for solving specific transcompiler issue like Babel js.
How the error is reproduced:
Transcompilers like Babel JS removes the types whilst transpiling,but it may happen sometimes that whilst transpiling it isn't sure whether a specific import is simply a type (that can be removed ) or an actual value(that is to be kept)
For example:
import { Type } from "./types"; const changeType = (val : Type) => { //some logic }; is transpiled to
const changeColor = (color) => { window.color = color; }; simply by removing the type.
But removing types simply isn't so obvious in this case:
import { Type } from "./types"; export { Type };
Hence, we need to explicity define these type imports as import type {Type} .
Otherwise,you should use the generic import {Type}

@andrewbranch andrewbranch added the Question An issue which isn't directly actionable in code label Aug 3, 2020
@andrewbranch
Copy link
Member

The intention is for you not to use import type unless you need to. There’s some discussion related to auto-import at #39432, and there’s a thorough description of the motivations for introducing the feature on the original PR: #35200.

If you don’t have a specific need for type-only imports, you could consider them a stylistic choice. My personal suggestion for how to consider that stylistic choice is

  • Best style: do not use import type. This style choice eliminates meaningless distinctions and reduces cognitive load, giving you more time and resources to think about things that matter.
  • Second-best style: enable "importsNotUsedAsValues": "error" in your tsconfig, then use import type only where the errors force you to.
  • Worst style: use import type as much as possible, separating values and types from the same module into separate import statements. There is simply no reason to do this, and since there are currently no tools that would enforce this style, it would fall on you to analyze and separate your declarations manually, wasting your valuable coding time.

@parzhitsky
Copy link
Author

Thanks, @andrewbranch, great to hear the author's intent first-hand 👍

I'd argue that the second presented option is actually the best one; import type, I think, is a useful feature, consistently avoiding using it would be kind of silly. That's up to debate though.

@Angelfire
Copy link

I apologize tremendously for reopening this very old thread. Now we have 3 ways to import types

import-type

Based on the discussion, I think I should then use the 3 way, right?
import { type Type, value } from "some-module";

@RyanCavanaugh
Copy link
Member

Those each have different meanings and you should use the one corresponding to the behavior you want to have happen.

@chribjel
Copy link

Those each have different meanings and you should use the one corresponding to the behavior you want to have happen.

Where can i read more about the different meaning between
import type { AuthState } from "..." and import { type AuthState } from "..."?

@parzhitsky
Copy link
Author

@chribjel Above all, the type in

import type { Thing, OtherThing } from "things"

… applies to both Thing and OtherThing, while in

import { type Thing, OtherThing } from "things"

… the type only applies to Thing, while OtherThing is imported as a value (if it is a value).

@chribjel
Copy link

@parzhitsky That is what i assumed, just got confused when Ryan said the three imports had different meaning.

If you only have ONE imported type they have the same "meaning", or at least ends up meaning the same thing.

@andrewbranch
Copy link
Member

If you only have ONE imported type they have the same "meaning", or at least ends up meaning the same thing.

Not under --verbatimModuleSyntax.

// index.ts
import type { Thing } from "things-1";
import { type Thing } from "things-2";

becomes

// index.js
import {} from "things-2";

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

6 participants