TypeScript 中的内置类型声明

Typescript 2.0 让你能够更细粒度地控制哪些内置的 API 声明可以被加入到项目中。在之前,如果你的项目的构建目标(target)是ES6,那么你只能访问 ES2015 的 API。现在,内置的标准库声明已经模块化,Typescript 已经允许你选择哪些类型声明需要加入到项目中。

--lib 编译器选项

Javascript 标准库的类型声明被拆分到了许多 API 组里。截止目前(2016 年 11 月底),已经定义了下面的这些组:

  • dom
  • webworker
  • es5
  • es6 / es2015
  • es2015.core
  • es2015.collection
  • es2015.iterable
  • es2015.promise
  • es2015.proxy
  • es2015.reflect
  • es2015.generator
  • es2015.symbol
  • es2015.symbol.wellknown
  • es2016
  • es2016.array.include
  • es2017
  • es2017.object
  • es2017.sharedmemory
  • scripthost

你可以通过命令行选项 --lib 或者 tsconfig.json 中的 lib 属性来传入你需要的以上 API 集合的子集。然后 Typescript 只会将你需要的类型声明注入到项目中,也就是说,其他 API 组的类型声明在你的项目环境中是不存在的。

如果你不显式地提供 lib 选项,Typescript 会隐式地注入 web 开发需要的一些 api 组。以下这些是默认值,具体由你项目的构建目标而定:

  • ["dom", "es5", "scripthost"],当构建目标是 ES5
  • ["dom", "es6", "dom.iterable", "scripthost"],当构建目标是 ES6

在构建目标是 ES5 的 Typescript 项目中使用 ES2015 的 Promise

假如你正在开发的项目构建目标是 ES5,以此来保证项目能够在大多数的浏览中正常运行。你的 tsconfig.json 大概会是这样的:

{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es5",
    "noImplicitAny": true,
    "strictNullChecks": true
  }
}

因为没有指定 lib 选项,Typescript 默认注入 "dom", "es5", 和 "scripthost" 这些 API 组。现在假设你想用 ES2015 中的 Promise API,但它在 ES5 中不存在,所以你需要安装 polyfill 来保证你的代码能够在低版本浏览器中正常运行:

npm install --save es6-promise

然后你在应用的入口模块中引入 polyfill:

import 'es6-promise'

// ...

引入 polyfill 以后,你就可以在你的应用中使用 Promise,你的代码也能正常运行。但是,TypeScript 会在编译阶段给出一个报错,提示 Cannot find the name 'Promise'。这是因为 Promise 的类型声明并没有在默认注入的 API 组中。

你需要告诉 Typescript,你确定 Promise 在运行时会存在(因为有 polyfill)。这个时候 lib 这个编译器选项就派上用场了:

注意,因为你覆盖了默认值,所以现在你需要显式地提供所有 API 组。最终的 tsconfig.json 文件应该是这样的:

{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es5",
    "noImplicitAny": true,
    "strictNullChecks": true,
    "lib": ["dom", "es5", "es2015.promise"]
  }
}

就这么简单,现在类型检查器又能开心工作了: