添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
GitHub

# 编译选项

本篇主要介绍 tsconfig.json 中与编译相关的选项。

{
  "compilerOptions": {
    "incremental": true,                // 增量编译
    "tsBuildInfoFile": "./buildFile",   // 增量编译文件的存储位置
    "diagnostics": true,                // 打印编译信息
    "target": "es5",           // 目标语言的版本
    "module": "commonjs",      // 生成代码的模块标准
    "outFile": "./app.js",     // 将多个相互依赖的文件生成一个文件,可以用在 AMD 模块中
    "lib": [],                 // TS 需要引用的库,即声明文件,es5 默认 "dom", "es5", "scripthost"
    "allowJs": true,           // 允许编译 JS 文件(js、jsx)
    "checkJs": true,           // 允许在 JS 文件中报错,通常与 allowJS 一起使用
    "outDir": "./out",         // 指定输出目录
    "rootDir": "./",           // 指定输入文件目录(用于输出)
    "declaration": true,         // 生成声明文件
    "declarationDir": "./d",     // 声明文件的路径
    "emitDeclarationOnly": true, // 只生成声明文件
    "sourceMap": true,           // 生成目标文件的 sourceMap
    "inlineSourceMap": true,     // 生成目标文件的 inline sourceMap
    "declarationMap": true,      // 生成声明文件的 sourceMap
    "typeRoots": [],             // 声明文件目录,默认 node_modules/@types
    "types": [],                 // 声明文件包
    "removeComments": true,    // 删除注释
    "noEmit": true,            // 不输出文件
    "noEmitOnError": true,     // 发生错误时不输出文件
    "noEmitHelpers": true,     // 不生成 helper 函数,需额外安装 ts-helpers
    "importHelpers": true,     // 通过 tslib 引入 helper 函数,文件必须是模块
    "downlevelIteration": true,    // 降级遍历器的实现(es3/5)
    "strict": true,                        // 开启所有严格的类型检查
    "alwaysStrict": false,                 // 在代码中注入 "use strict";
    "noImplicitAny": false,                // 不允许隐式的 any 类型
    "strictNullChecks": false,             // 不允许把 null、undefined 赋值给其他类型变量
    "strictFunctionTypes": false,          // 不允许函数参数双向协变
    "strictPropertyInitialization": false, // 类的实例属性必须初始化
    "strictBindCallApply": false,          // 严格的 bind/call/apply 检查
    "noImplicitThis": false,               // 不允许 this 有隐式的 any 类型
    "noUnusedLocals": true,                // 检查只声明,未使用的局部变量
    "noUnusedParameters": true,            // 检查未使用的函数参数
    "noFallthroughCasesInSwitch": true,    // 防止 switch 语句贯穿
    "noImplicitReturns": true,             // 每个分支都要有返回值
    "esModuleInterop": true,               // 允许 export = 导出,由import from 导入
    "allowUmdGlobalAccess": true,          // 允许在模块中访问 UMD 全局变量
    "moduleResolution": "node",            // 模块解析策略
    "baseUrl": "./",                       // 解析非相对模块的基地址
    "paths": {                             // 路径映射,相对于 baseUrl
      "jquery": ["node_modules/jquery/dist/jquery.slim.min.js"]
    "rootDirs": ["src", "util"],           // 将多个目录放在一个虚拟目录下,用于运行时
    "listEmittedFiles": true,        // 打印输出的文件
    "listFiles": true,               // 打印编译的文件(包括引用的声明文件)

接下来,我们会逐个分析上面的配置项。

# incremental

它的含义是增量编译,TypeScript 编译器在第一次编译后会生成一个可以编译信息的文件,在之后的编译之后会根据这个文件提高编译的速度。该文件默认会在根目录下名称为 tsconfig.tsbuildinfo

{
  "program": {
    "fileInfos": {
      "../../../../../usr/local/lib/node_modules/typescript/lib/lib.d.ts": {
        "version": "49ff9798f592c8b7e628fd881401e68810c1b3589ecd7a41b32b3c287374cde0",
        "signature": "49ff9798f592c8b7e628fd881401e68810c1b3589ecd7a41b32b3c287374cde0"
      "../../../../../usr/local/lib/node_modules/typescript/lib/lib.es5.d.ts": {
        "version": "ff5688d6b2fcfef06842a395d7ff4d5730d45b724d4c48913118c889829052a1",
        "signature": "ff5688d6b2fcfef06842a395d7ff4d5730d45b724d4c48913118c889829052a1"
      "../../../../../usr/local/lib/node_modules/typescript/lib/lib.dom.d.ts": {
        "version": "2d53f3741e5a4f78a90f623387d71a1cc809bb258f10cdaec034b67cbf71022f",
        "signature": "2d53f3741e5a4f78a90f623387d71a1cc809bb258f10cdaec034b67cbf71022f"
      "../../../../../usr/local/lib/node_modules/typescript/lib/lib.webworker.importscripts.d.ts": {
        "version": "fe4e59403e34c7ff747abe4ff6abbc7718229556d7c1a5b93473fb53156c913b",
        "signature": "fe4e59403e34c7ff747abe4ff6abbc7718229556d7c1a5b93473fb53156c913b"
      "../../../../../usr/local/lib/node_modules/typescript/lib/lib.scripthost.d.ts": {
        "version": "b9faa17292f17d2ad75e34fac77dd63a6403af1dba02d39cd0cbb9ffdf3de8b9",
        "signature": "b9faa17292f17d2ad75e34fac77dd63a6403af1dba02d39cd0cbb9ffdf3de8b9"
      "./src/index.ts": {
        "version": "a0e2a405f15ab7f6218e22c622acc2706d51eae2aa90f302f81f68628e22cd55",
        "signature": "ec8f4696ee1308e5fbc9f50626f5677f0f15bd7c228311cbcc0669233461fa1d"
    "options": {
      "incremental": true,
      "configFilePath": "./tsconfig.json"
    "referencedMap": {},
    "exportedModulesMap": {},
    "semanticDiagnosticsPerFile": [
      "../../../../../usr/local/lib/node_modules/typescript/lib/lib.d.ts",
      "./src/index.ts",
      "../../../../../usr/local/lib/node_modules/typescript/lib/lib.es5.d.ts",
      "../../../../../usr/local/lib/node_modules/typescript/lib/lib.dom.d.ts",
      "../../../../../usr/local/lib/node_modules/typescript/lib/lib.webworker.importscripts.d.ts",
      "../../../../../usr/local/lib/node_modules/typescript/lib/lib.scripthost.d.ts"
  "version": "3.6.2"

# tsBuildInfoFile

可以修改增量编译文件的存储文件夹和文件名

# diagnostics

打印编译信息。

Files:            6
Lines:        24817
Nodes:       111372
Identifiers:  41045
Symbols:      27914
Types:         8268
Memory used: 68338K
I/O read:     0.01s
I/O write:    0.00s
Parse time:   0.42s
Bind time:    0.23s
Check time:   1.13s
Emit time:    0.02s
Total time:   1.80s

# target

设置目标语言的版本,可设置为 ES3 ES5 ES2015 等等,默认为 ES3

# module

设置生成代码的模块标准,可以设置为 CommonJS AMD UMD 等等。

# outFile

将多个相互依赖的文件生成一个文件,可以用在 AMD 模块中。

我们创建两个文件,分别为 index.ts amd.ts ,如下所示:

// ./src/index.ts
import a = require('./amd')
let str: string = 'abc'
// ./src/amd.ts
let amd: number = 0
export = amd

index.ts 引入 amd.ts ,我们再设置一下 tsconfig.json 文件。

{
  "compilerOptions": {
    "module": "amd",
    "outFile": "./app.js"

然后在命令行执行 tsc 命令,编译器会将两个 ts 文件合并编译成一个 app.js 文件。

define("amd", ["require", "exports"], function (require, exports) {
    "use strict";
    var amd = 0;
    return amd;
});
define("index", ["require", "exports"], function (require, exports) {
    "use strict";
    exports.__esModule = true;
    var str = 'abc';
});

# lib

指定 ts 需要引用的库,即声明文件,若 target 设置为 es5 时, lib 默认为 ["dom", "es5", "scripthost"]

例如,我们想在 ts 中使用 es2019 的方法。可以在 lib 配置里添加 es2019

# allowJs

允许编译器编译 JS 文件(js、jsx)。

# checkJs

允许在 JS 文件中报错,通常与 allowJS 一起使用。

# outDir

指定输出目录

# rootDir

指定输入文件目录

# declaration

编译器编译时,允许生成声明文件( .d.ts )。

# declarationDir

指定声明文件的生成的目录。

# emitDeclarationOnly

编译器编译时,只允许生成声明文件。

# sourceMap

编译器编译时,生成目标文件的 sourceMap 文件。

# inlineSourceMap

编译器编译时,将 sourceMap 生成在 js 文件中。

# declarationMap

编译器编译时,生成声明文件的 sourceMap。

# typeRoots

设置声明文件目录,默认 node_modules/@types

# types

这是声明文件包,如果设置了某一个声明文件,那么编译器只会加载这个声明文件。

# removeComments

是否删除注释

# noEmit

执行 tsc 不会输出任何文件

# noEmitOnError

发生错误时不输出文件

# noEmitHelpers

设置为 true 时,不生成 helper 函数。先看下面示例:

class B {}
class A extends B {}
export = A

我们创建了一个模块。然后在控制台执行 tsc ,下面就是编译后的结果:

"use strict";
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
})();
var B = /** @class */ (function () {
    function B() {
    return B;
}());
var A = /** @class */ (function (_super) {
    __extends(A, _super);
    function A() {
        return _super !== null && _super.apply(this, arguments) || this;
    return A;
}(B));
module.exports = A;

编译器会自动生成 __extends

如果我们将 noEmitHelpers 这个配置设置为 true 之后。编译后的结果如下:

"use strict";
var B = /** @class */ (function () {
    function B() {
    return B;
}());
var A = /** @class */ (function (_super) {
    __extends(A, _super);
    function A() {
        return _super !== null && _super.apply(this, arguments) || this;
    return A;
}(B));
module.exports = A;

上面的编译后的结果中 __extends 未定义。 ts 已经为开发者定义了一个配置项,方便解决该问题。 就是接下来要介绍的配置 importHelpers

# importHelpers

通过 tslib 引入 helper 函数,文件必须是模块。编译结果如下:

"use strict";
var tslib_1 = require("tslib");
var B = /** @class */ (function () {
    function B() {
    return B;
}());
var A = /** @class */ (function (_super) {
    tslib_1.__extends(A, _super);
    function A() {
        return _super !== null && _super.apply(this, arguments) || this;
    return A;
}(B));
module.exports = A;

若提示 tslib 未找到时,可以手动安装它。

# downlevelIteration

降级遍历器的实现,下面是一个 es6 语法:

let a = [1, 2, 3]
let b = [4, ...a]

我们打开这项配置,进行编译后结果如下:

var __read = (this && this.__read) || function (o, n) {
    var m = typeof Symbol === "function" && o[Symbol.iterator];
    if (!m) return o;
    var i = m.call(o), r, ar = [], e;
    try {
        while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
    catch (error) { e = { error: error }; }
    finally {
        try {
            if (r && !r.done && (m = i["return"])) m.call(i);
        finally { if (e) throw e.error; }
    return ar;
var __spread = (this && this.__spread) || function () {
    for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
    return ar;
var a = [1, 2, 3];
var b = __spread([4], a);

会生成两个 helper 函数。

# strict

表示开启所有严格的类型检查,若 strict 为 true, alwaysStrict noImplicitAny strictNullChecks strictFunctionTypes strictPropertyInitialization strictBindCallApply noImplicitThis 选项默认都为 true。

# alwaysStrict

在代码中注入 use strict

# noImplicitAny

不允许隐式的 any 类型。

# strictNullChecks

不允许把 null undefined 赋值给其他类型变量。

# strictFunctionTypes

不允许函数参数双向协变。

# strictPropertyInitialization

类的实例属性必须初始化。

# strictBindCallApply

严格的 bind call apply 检查。

function add (a: number, b: number) {
  return a + b
add.call(undefined, 1, '2')
// Error: Argument of type '"2"' is not assignable to parameter of type 'number'.

# noImplicitThis

不允许 this 有隐式的 any 类型。

class A {
  name: string = 'abc'
  getName () {
    return function () {
      console.log(this.name)
// Error: 'this' implicitly has type 'any' because it does not have a type annotation.

# noUnusedLocals

检查只声明,未使用的局部变量

# noUnusedParameters

检查未使用的函数参数

# noFallthroughCasesInSwitch

防止 switch 语句贯穿

# noImplicitReturns

每个分支都要有返回值

# esModuleInterop

允许 export = 方式导出,也可以用 import = 的方式导入。

# allowUmdGlobalAccess

允许在模块中访问 UMD 全局变量

# moduleResolution

模块解析策略,这里提供两种解析策略 node classic ts 默认使用 node 解析策略。

  • classic 模块解析策略

适用于 AMD System ES2015

如果一个模块使用相对方式导入时, ts 就会依次解析同级目录 .ts .d.ts 文件。

// /root/src/moduleA.ts
import { b } from './moduleB'
 * /root/src/moduleB.ts
 * /root/src/moduleB.d.ts

如果使用非相对方式导入时如下, ts 会从当前目录的 node_modules 目录里查找,如果未找到,会依次向上级目录查找。

// /root/src/moduleA.ts
import { b } from 'moduleB'
 * /root/src/node_modules/moduleB.ts
 * /root/src/node_modules/moduleB.d.ts
 * /root/node_modules/moduleB.ts
 * /root/node_modules/moduleB.d.ts
 * /node_modules/moduleB.ts
 * /node_modules/moduleB.d.ts
  • node 模块解析策略

使用相对方式导入

// /root/src/moduleA.ts
import { b } from './moduleB'
 * /root/src/moduleB.ts
 * /root/src/moduleB.tsx
 * /root/src/moduleB.d.ts
 * /root/src/moduleB/package.json ( types 属性)
 * /root/src/moduleB/index.ts
 * /root/src/moduleB/index.tsx
 * /root/src/moduleB/index.d.ts

使用非相对方式导入

// /root/src/moduleA.ts
import { b } from 'moduleB'
 * /root/src/node_modules/moduleB.ts
 * /root/src/node_modules/moduleB.tsx
 * /root/src/node_modules/moduleB.d.ts
 * /root/src/node_modules/package.json ( types 属性)
 * /root/src/node_modules/index.ts
 * /root/src/node_modules/index.tsx
 * /root/src/node_modules/index.d.ts
 * 依次向上目录查找

# baseUrl

解析非相对模块的基地址,默认为当前目录

# paths

路径映射,相对于 baseUrl。比如示例中我们想引入 jquery 精简版本,可以制定它的相对路径。

# rootDirs

将多个目录放在一个虚拟目录下,用于运行时。

比如 我们创建量以下两个文件。

// /util/a.ts
let a: string = 'A'
export = a
// /src/index.ts
import a from './a'

注意在引入 a 时,是引入的当前目录。因为当 rootDirs 设置了 src util 目录时,编译器默认它们属于同级目录。

# listEmittedFiles

打印输出的文件。

# listFiles

打印编译的文件,包括引用的声明文件。

Last Updated: 10/30/2019, 10:49:17 AM