一种「预期」的行为
在 TypeScript 中,如果导入的模块没有用于任何表达式,TypeScript 将会删除该模块导入。
import { xxx } from './module';
let a: xxx = /* something */;
复制代码
编译后:
var a = /* ssomething */;
复制代码
如果你需要强制导入该模块,你可以使用 import 'module'
语法:
import './module';
复制代码
这有时候非常糟糕,试想如果一个模块如果含有副作用,但是并没有用到任何表达式中:
// source-component.ts
export class SourceComponent extends HTMLElement {
// 其他代码
}
customElements.define('source-component', SourceComponent);
复制代码
import {SourceComponent} from './source-component.js';
const example = document.createElement('source-component') as SourceComponent;
复制代码
在正常编译时,TypeScript 将会在编码者毫不知情的情况下舍弃 source-component.ts
文件。待到提测阶段,你可能才会发现问题所在,查找、抱怨之后,会加上 import './source-component.js'
这样一行代码,来让编译器强制导入该模块。
其次,使用 isolatedModules
编译选项时,以下代码。会出现编译错误的问题:
export { AType } from './module' // Cannot re-export a type when the '--isolatedModules' flag is provided
复制代码
在笔者查阅相关资料后,了解到 isolatedModules
编译选项,其实是「确保我的程序代码可以被不进行任何类型检查的编译器正确地编译」(如 babel)。
当在 babel 运行以下程序时,也会抛出错误:
// Export 'MyType' is not defined
export { MyType } from './module';
复制代码
为了正常编译通过,你需要改成如下方式:
import { AType as BType } from './module';
export type AType = BType;
// 或者
export type AType = import('./module').AType
复制代码
仅导入/导出类型
在即将到来的 3.8 版本中,有一个提案 import type
,旨在解决上述中的问题。
它提供了以下语法:
import type T from './mod';
import type { A, B } from './mod';
import type * as Types from './mod';
export type { T };
export type { T } from './mod';
复制代码
import type
用来告诉 TypeScript 编译器,仅仅是导入/导出类型:
// a.ts
export default calss A{}
// b.ts
import type A from './a';
new A(); // error,
function f(obj: A) {} // ok
复制代码
因此在默认情况下,TypeScript 将不会再删除任何 import
导入语句:
import { T } from './module';
import x: T;
复制代码
编译后:
import "./module";
let x;
复制代码
并且对于在使用 isolatedModules
编译选项时,export { AType } from './module'
的问题,只需改写成 export type { T } from './mod';
即可解决。
ps: TypeScript 3.8 大概在 2020 年 2 月发布。
参考
如果你对 TypeScript 感兴趣,可以通过京东、当当等渠道购买《深入理解 TypeScript》。
或者你也可以关注下面公众号,获取更多内容