简体   繁体   中英

Is `import type` equivalent to `import()`

Are

import type { Foo, Bar as Baz } from './'

and

type Foo = import('./').Foo
type Bar = import('./').Baz

equivalent?

Please be aware that the import() in this context is not a dynamic import but import types introduced in TypeScript 2.9. You can enter both examples into the TypeScript playground to verify that the syntax/types are valid.

I want to use import type but also create declarations for TS < 3.8.

If the above assertion is true I could apply an AST transform to the emitted declaration files.

They are not equivalent, though they are often interchangeable in practice. There are two differences that can matter, depending on the context.

import type makes a file a module.

The TypeScript compiler determines whether a TypeScript file's top level scope is module-scoped or globally scoped (ie, whether the file is a module or a script) by the presence of any import or export declarations. import type counts as an import declaration, so if it were the only import/export statement in the file, substituting a type alias for it would change the file from a module to a script. The practical implication of this is that if you have a file (usually adts file) that you need to be global, but want to reference types from a module, you're stuck using type Foo = import(...) .

import type can reference value and namespace meanings.

When you declare a type alias with type Foo = import('./').Bar , Foo is purely a type, even if Bar had both a type and a value meaning (eg class Bar {} ). You have completely left the value side of Bar behind in this declaration. import type actually references the full Bar symbol and all its meanings, it just sets up a syntactic check that ensures you never use it in a position that would get emitted to JS (since the import statement will get erased in JS). This matters in a few places, easiest to show with an example:

import type { EventEmitter as EE1 } from "events";
type EE2 = import("events").EventEmitter;

// Ok, because `declare` means `Foo1` is not actually referenced
// in an emitting position.
declare class Derived1 extends EE1 {}

declare class Derived2 extends EE2 {}
//                             ^^^
// Error: 'EE2' only refers to a type, but is being used as a value here.

type EventEmitterCtor1 = typeof EE1; // Ok
type EventEmitterCtor2 = typeof EE2;
//                              ^^^
// Error: 'EE2' only refers to a type, but is being used as a value here.

const x = EE1;
//        ^^^
// Error: 'EE1' cannot be used as a value because it was imported using 'import type'

const y = EE2;
//        ^^^
// 'EE2' only refers to a type, but is being used as a value here.

(Playground link)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM