tsconfig.json

TypeScript 1.5 版本之前缺少一种内置的方法能够管理 TypeScript 工程的配置。在 TypeScript 1.5 版本中,提供了使用 tsconfig.json 配置文件来管理 TypeScript 工程的功能,从而弥补了这个不足。

tsconfig.json 配置文件能够管理如下种类的工程配置:

  • 编译文件列表。

  • 编译选项。

  • tsconfig.json 配置文件间的继承关系(TypeScript 2.1)。

  • 工程间的引用关系(TypeScript 3.0)。

本节中将介绍如何为 TypeScript 工程添加 tsconfig.json 配置文件,并使用该配置文件来管理工程中的编译文件列表和声明文件列表。在本节的最后将介绍 tsconfig.json 配置文件的继承,它允许我们重用配置文件,同时也遵循了 DRY(Don’t repeat yourself)原则。

使用配置文件

tsconfig.json 配置文件是一个 JSON 格式的文件。若一个目录中存在 tsconfig.json 文件,那么该目录将被编译器视作 TypeScript 工程的根目录。

假设当前工程目录结构如下:

C:\app
|-- src
|   `-- index.ts
`-- tsconfig.json

此例中,C:\app 目录下包含了一个 tsconfig.json 文件,因此 C:\app 成了一个 TypeScript 工程,并且 C:\app 目录将被视为工程的根目录。

tsconfig.json 文件的内容如下:

{
    "compilerOptions": {
        "target": "ES5"
    }
}

在编写好 tsconfig.json 配置文件之后,有以下两种方式来使用它:

  • 运行 tsc 命令时,让编译器自动搜索 tsconfig.json 配置文件。

  • 运行 tsc 命令时,使用 --project-p 编译选项指定使用的 tsconfig.json 配置文件。

需要注意的是,如果运行 tsc 命令时指定了输入文件,那么编译器将忽略 tsconfig.json 配置文件,既不会自动搜索配置文件,也不会使用指定的配置文件。示例如下:

tsc index.ts -p tsconfig.json

此例中,在运行 tsc 命令时指定了输入文件 index.ts,因此编译器将不使用指定的 tsconfig.json 配置文件。

自动搜索配置文件

在运行 tsc 命令时,若没有使用 --project-p 编译选项,那么编译器将在 tsc 命令的运行目录下查找是否存在文件名为 tsconfig.json 的配置文件。若存在 tsconfig.json 配置文件,则使用该配置文件来编译工程;若不存在,则继续在父级目录下查找 tsconfig.json 配置文件,直到搜索到系统根目录为止;如果最终也未能找到一个可用的 tsconfig.json 配置文件,那么就会停止编译工程。

假设当前工程目录结构如下:

C:\app
|-- src
|   `-- index.ts
`-- tsconfig.json

当在 C:\app\src 目录下运行 tsc 命令时,编译器搜索 tsconfig.json 配置文件的流程如下:

  1. 搜索 C:\app\src\tsconfig.json

  2. 搜索 C:\app\tsconfig.json

  3. 搜索 C:\tsconfig.json

  4. 退出 tsc 编译命令,不进行编译。

一旦编译器找到了匹配的 tsconfig.json 配置文件,就会终止查找过程并使用找到的配置文件。此例中,在第 2 步能够找到匹配的 tsconfig.json 配置文件,于是使用该配置文件来编译工程,并终止后续的查找。

指定配置文件

在运行 tsc 命令时,可以使用 --project 编译选项(短名字为 -p)来指定使用的配置文件。

--project 编译选项的参数是一个路径,它的值可以为:

  • 指向某个具体的配置文件。在这种情况下,配置文件的文件名不限,例如可以使用名为 app.config.json 的配置文件。

  • 指向一个包含了 tsconfig.json 配置文件的目录。在这种情况下,该目录中必须包含一个名为 tsconfig.json 的配置文件。

假设当前工程目录结构如下:

C:\app
|-- src
|   `-- index.ts
|-- tsconfig.json
`-- tsconfig.release.json

C:\app 目录下运行 tsc 命令并使用 -p 编译选项来指定使用 tsconfig.release.json 配置文件编译该工程。示例如下:

tsc -p tsconfig.release.json

C:\app 目录下运行 tsc 命令并使用 -p 编译选项来指定一个包含了 tsconfig.json 配置文件的目录。示例如下:

tsc -p .

此例中,-p 编译选项的参数值为一个点符号 .,它表示当前目录,也就是运行 tsc 命令时所在的目录。因此,编译器会查找并使用 C:\app\tsconfig.json 配置文件。

编译选项列表

tsconfig.json 配置文件中使用顶层的 compilerOptions 属性能够设置编译选项。对于同一个编译选项而言,不论是在命令行上指定还是在 tsconfig.json 配置文件中指定,它们都具有相同的效果并且使用相同的名称。示例如下:

{
    "compilerOptions": {
        "strict": true,
        "target": "ES5"
    }
}

注意,不是所有的编译选项都能够在 tsconfig.json 配置文件中指定。例如,前文介绍的 --help--version 编译选项不支持在 tsconfig.json 配置文件中使用。

TypeScript 提供了一个 --init 编译选项,在命令行上运行 tsc 命令并使用 --init 编译选项会初始化一个 tsconfig.json 配置文件。在生成的 tsconfig.json 配置文件中会自动添加一些常用的编译选项并将它们分类。

假设当前工程目录结构如下:

C:\app
`-- index.ts

C:\app 目录下运行 tsc 命令并使用 --init 编译选项。示例如下:

tsc --init

tsc 命令的运行结果是在 C:\app 目录下新生成了一个 tsconfig.json 配置文件。该文件的内容如下:

{
    "compilerOptions": {
        /* 基础选项 */
        "incremental": true,
        "target": "es5",
        "module": "commonjs",
        "lib": [],
        "allowJs": true,
        "checkJs": true,
        "jsx": "preserve",
        "declaration": true,
        "declarationMap": true,
        "sourceMap": true,
        "outFile": "./",
        "outDir": "./",
        "rootDir": "./",
        "composite": true,
        "tsBuildInfoFile": "./",
        "removeComments": true,
        "noEmit": true,
        "importHelpers": true,
        "downlevelIteration": true,
        "isolatedModules": true,

        /* 严格类型检查选项 */
        "strict": true,
        "noImplicitAny": true,
        "strictNullChecks": true,
        "strictFunctionTypes": true,
        "strictBindCallApply": true,
        "strictPropertyInitialization": true,
        "noImplicitThis": true,
        "alwaysStrict": true,

        /* 额外检查选项 */
        "noUnusedLocals": true,
        "noUnusedParameters": true,
        "noImplicitReturns": true,
        "noFallthroughCasesInSwitch": true,

        /* 模块解析选项 */
        "moduleResolution": "node",
        "baseUrl": "./",
        "paths": {},
        "rootDirs": [],
        "typeRoots": [],
        "types": [],
        "allowSyntheticDefaultImports": true,
        "esModuleInterop": true,
        "preserveSymlinks": true,
        "allowUmdGlobalAccess": true,

        /* SourceMap 选项 */
        "sourceRoot": "",
        "mapRoot": "",
        "inlineSourceMap": true,
        "inlineSources": true,

        /* 实验性选项 */
        "experimentalDecorators": true,
        "emitDecoratorMetadata": true,

        /* 高级选项 */
        "forceConsistentCasingInFileNames": true
    }
}

编译文件列表

tsconfig.json 配置文件的另一个主要用途是配置待编译的文件列表。

--listFiles 编译选项

TypeScript 提供了一个 --listFiles 编译选项,如果启用了该编译选项,那么在编译工程时,编译器将打印出参与本次编译的文件列表。该编译选项既可以在命令行上使用,也可以在 tsconfig.json 配置文件中使用。

假设当前工程目录结构如下:

C:\app
`-- src
    |---a.ts
    `-- b.ts

在命令行上使用 --listFiles 编译选项,示例如下:

tsc --listFiles

tsconfig.json 配置文件中使用 --listFiles 编译选项,示例如下:

{
    "compilerOptions": {
        "listFiles": true,
        "strict": true,
        "target": "ES5"
    }
}

在使用上例中的 tsconfig.json 配置文件编译工程时,编译器将输出编译文件列表。示例如下:

...\typescript\lib\lib.d.ts
...\typescript\lib\lib.es5.d.ts
...\typescript\lib\lib.dom.d.ts
...\typescript\lib\lib.webworker.importscripts.d.ts
...\typescript\lib\lib.scripthost.d.ts

C:\app\src\a.ts
C:\app\src\b.ts

通过以上运行结果能够看到,编译文件列表除了包含工程内的源文件外还包含了 TypeScript 内置的一些声明文件。

默认编译文件列表

如果工程中含有一个 tsconfig.json 配置文件,那么在默认情况下 tsconfig.json 配置文件所在目录及其子目录下的所有 .ts.d.ts.tsx 文件都会被添加到编译文件列表。

假设当前工程目录结构如下:

C:\app
|-- a.ts
|-- src
|   |-- b.ts
|   `-- c.ts
`-- tsconfig.json

tsconfig.json 配置文件内容如下:

{
    "compilerOptions": {
        "listFiles": true
    }
}

C:\app 目录下运行 tsc 编译命令,示例如下:

tsc

tsc 命令的运行结果如下:

<此处省略了内置的声明文件列表>

C:\app\a.ts
C:\app\src\b.ts
C:\app\src\c.ts

通过以上运行结果能够看到,C:\app 目录与其子目录 C:\app\src 下的所有 TypeScript 源文件都参与了本次编译。

files 属性

tsconfig.json 配置文件中,使用顶层的 files 属性能够定义编译文件列表。files 属性的值是由待编译文件路径所构成的数组。

假设当前工程目录结构如下:

C:\app
|-- a.ts
|-- src
|   |-- b.ts
|   `-- c.ts
`-- tsconfig.json

tsconfig.json 配置文件内容如下:

{
    "compilerOptions": {
        "listFiles": true
    },
    "files": ["src/b.ts", "src/c.ts"]
}

C:\app 目录下运行 tsc 命令,示例如下:

tsc

tsc 命令的运行结果如下:

<此处省略了内置的声明文件列表>

C:\app\src\b.ts
C:\app\src\c.ts

通过以上运行结果能够看到,只有 files 属性中指定的 C:\app\src\b.tsC:\app\src\c.ts 文件参与了本次编译,而 C:\app\a.ts 文件则没有参与编译。

在使用 files 属性设置编译文件列表时必须逐一地列出每一个文件,该属性不支持进行模糊的文件匹配。因此,files 属性适用于待编译文件数量较少的情况。当待编译文件数量较多时,使用 includeexclude 属性是更好的选择。

include 属性

tsconfig.json 配置文件中,使用顶层的 include 属性能够定义编译文件列表。include 属性的功能包含了 files 属性的功能,它既支持逐一地列出每一个待编译的文件,也支持使用通配符来模糊匹配待编译的文件。

include 属性支持使用三种通配符来匹配文件,具体请参考8.1.2节。

假设当前工程目录结构如下:

C:\app
|-- bar
|   `-- c.ts
|-- foo
|   |-- a.spec.ts
|   |-- a.ts
|   |-- b.spec.ts
|   `-- b.ts
`-- tsconfig.json

如果 tsconfig.json 配置文件的内容如下:

{
    "include": ["foo/*.spec.ts"]
}

那么只有 C:\app\foo\a.spec.tsC:\app\foo\b.spec.ts 文件会被添加到编译文件列表。

如果 tsconfig.json 配置文件的内容如下:

{
    "include": ["foo/?.ts"]
}

那么只有 C:\app\foo\a.tsC:\app\foo\b.ts 文件会被添加到编译文件列表。

如果 tsconfig.json 配置文件的内容如下:

{
    "include": ["bar/**/*.ts"]
}

那么只有 C:\app\bar\c.ts 文件会被添加到编译文件列表。

exclude属性

tsconfig.json 配置文件中,exclude 属性需要与 include 属性一起使用,它的作用是从 include 属性匹配到的文件列表中去除指定的文件。exclude 属性也支持和 include 属性相同的通配符。

假设当前工程目录结构如下:

C:\app
|-- bar
|   `-- c.ts
|-- foo
|   |-- a.spec.ts
|   |-- a.ts
|   |-- b.spec.ts
|   `-- b.ts
`-- tsconfig.json

tsconfig.json 配置文件的内容如下:

{
    "compilerOptions": {
        "listFiles": true
    },
    "include": ["**/*"],
    "exclude": ["**/*.spec.ts"]
}

C:\app 目录下运行 tsc 命令,示例如下:

tsc

tsc 命令的运行结果如下:

<此处省略了内置的声明文件列表>

C:\app\bar\c.ts
C:\app\foo\a.ts
C:\app\foo\b.ts

此例中,include 属性将 C:\app 目录下所有的 .ts 文件添加到编译文件列表,然后 exclude 属性则将所有的 .spec.ts 文件从编译文件列表中移除。

声明文件列表

TypeScript 工程中 node_modules/@types 目录是一个特殊的目录,TypeScript 将其视为第三方声明文件的根目录,因为在安装 DefinitelyTyped 提供的声明文件时,它会被安装到 node_modules/@types 目录下。在默认情况下,编译器会将安装在 node_modules/@types 目录下的所有声明文件添加到编译文件列表。该默认行为可以使用 --typeRoots--types 编译选项设置。

--typeRoots 编译选项

--typeRoots 编译选项用来设置声明文件的根目录。当配置了 --typeRoots 编译选项时,只有该选项指定的目录下的声明文件会被添加到编译文件列表,而 node_modules/@types 目录下的声明文件将不再被默认添加到编译文件列表。

假设当前工程目录结构如下:

C:\app
|-- node_modules
|   `-- @types
|       `-- jquery
|       |   |-- ...
|       |   |-- index.d.ts
|       |   `-- package.json
|       `-- ...
|-- typings
|   `-- utils
|       `-- index.d.ts
|-- index.ts
|-- package.json
|-- package-lock.json
`-- tsconfig.json

tsconfig.json 配置文件的内容如下:

{
    "compilerOptions": {
        "listFiles": true,
        "typeRoots": ["./typings"]
    }
}

注意,typeRoots 属性中的路径是相对于当前 tsconfig.json 配置文件的路径来进行解析的。

C:\app 目录下运行 tsc 命令,示例如下:

tsc

tsc 命令的运行结果如下:

<此处省略了内置的声明文件列表>

C:\app\index.ts
C:\app\typings\utils\index.d.ts

通过该运行结果能够看到,只有 typeRoots 属性定义的 C:\app\typings 目录下的声明文件被添加到了编译文件列表,而 C:\app\node_modules\@types 目录下的声明文件则没有被添加到编译文件列表。

如果想要同时使用 C:\app\typingsC:\app\node_modules\@types 目录下的声明文件,则需要将两者同时添加到 typeRoots 属性中。示例如下:

{
    "compilerOptions": {
        "listFiles": true,
        "typeRoots": [
            "./node_modules/@types",
            "./typings"
        ]
    }
}

C:\app 目录下运行 tsc 命令的运行结果如下:

<此处省略了内置的声明文件列表>

C:\app\index.ts
C:\app\typings\utils\index.d.ts
C:\app\node_modules\@types\jquery\index.d.ts

--types 编译选项

--types 编译选项也能够用来指定使用的声明文件。--typeRoots 编译选项配置的是含有声明文件的目录,而 --types 编译选项则配置的是具体的声明文件。

假设当前工程目录结构如下:

C:\app
|-- node_modules
|   `-- @types
|       |-- jquery
|       |   |-- index.d.ts
|       |   `-- package.json
|       `-- lodash
|           |-- index.d.ts
|           `-- package.json
|-- index.ts
|-- package.json
|-- package-lock.json
`-- tsconfig.json

tsconfig.json 配置文件的内容如下:

{
    "compilerOptions": {
        "listFiles": true,
        "types": ["jquery"]
    }
}

C:\app 目录下运行 tsc 命令,示例如下:

tsc --listFiles

tsc 命令的运行结果如下:

<此处省略了内置的声明文件列表>

C:\app\index.ts
C:\app\node_modules\@types\jquery\index.d.ts

通过以上运行结果能够看到,只有 types 属性中定义的 jQuery 声明文件被添加到了编译文件列表,而 C:\app\node_modules\@types\lodash\index.d.ts 声明文件则没有被添加到编译文件列表。

继承配置文件

一个 tsconfig.json 配置文件可以继承另一个 tsconfig.json 配置文件中的配置。当一个项目中包含了多个 TypeScript 工程时,我们可以将工程共同的配置提取到 tsconfig.base.json 配置文件中,其他的 tsconfig.json 配置文件继承 tsconfig.base.json 配置文件中的配置。这种方式避免了重复配置同一属性并且能够增强可维护性,当需要修改某一共通属性时,仅需要修改一处即可。

tsconfig.json 配置文件中,使用顶层的 extends 属性来设置要继承的 tsconfig.json 配置文件。在 extends 属性中指定的路径既可以是相对路径,也可以是绝对路径,但路径解析规则有所不同。

--showConfig 编译选项

在介绍配置文件的继承之前,先介绍一下 --showConfig 编译选项。在使用该编译选项后,编译器将显示出编译工程时使用的所有配置信息。当我们在调试工程配置的时候,该编译选项是非常有帮助的。

但需要注意的是,若启用了 --showConfig 编译选项,那么编译器将不会真正编译一个工程,而只是显示工程的配置。

假设当前工程目录结构如下:

C:\app
|-- src
|   `-- index.ts
`-- tsconfig.json

tsconfig.json 配置文件的内容如下:

{
    "compilerOptions": {
        "listFiles": true,
        "target": "ES6"
    }
}

C:\app 目录下运行 tsc 命令,示例如下:

tsc

tsc 命令的运行结果如下:

{
    "compilerOptions": {
        "target": "es6"
    },
    "files": [
        "./src/index.ts"
    ]
}

该结果显示了在编译工程时最终使用的配置信息,它不但包含了 tsconfig.json 配置文件中的配置信息,还包含了待编译的文件列表。

注意,--showConfig 编译选项只能在命令行上使用,在 tsconfig.json 配置文件中不能使用该编译选项。

使用相对路径

extends 属性中指定的路径是以 ./../ 作为起始的,那么编译器在解析相对路径时将参照当前 tsconfig.json 配置文件所在的目录。

假设当前工程目录结构如下:

C:\app
|-- src
|   `-- index.ts
|-- tsconfig.app.json
|-- tsconfig.base.json
`-- tsconfig.spec.json

tsconfig.base.json 配置文件中包含了共同的配置,而 tsconfig.app.json 配置文件和 tsconfig.spec.json 配置文件继承了 tsconfig.base.json 配置文件中的配置。

tsconfig.base.json 文件的内容如下:

{
    "compilerOptions": {
        "target": "ES6"
    }
}

tsconfig.app.json 文件的内容如下:

{
    "extends": "./tsconfig.base.json",
    "compilerOptions": {
        "strict": true
    },
    "files": ["./src/index.ts"]
}

tsconfig.spec.json 文件的内容如下:

{
    "extends": "./tsconfig.base.json",
    "compilerOptions": {
        "strict": false
    },
    "files": ["./src/index.spec.ts"]
}

C:\app 目录下运行 tsc 命令,并使用 tsconfig.app.json 配置文件来编译该工程。示例如下:

tsc --showConfig -p tsconfig.app.json

tsc 命令的运行结果如下:

{
    "compilerOptions": {
        "target": "es6",
        "strict": true
    },
    "files": [
        "./src/index.ts"
    ]
}

C:\app 目录下运行 tsc 命令,并使用 tsconfig.spec.json 配置文件来编译该工程。示例如下:

tsc --showConfig -p tsconfig.spec.json

tsc 命令的运行结果如下:

{
    "compilerOptions": {
        "target": "es6",
        "strict": false
    },
    "files": [
        "./src/index.spec.ts"
    ]
}

通过以上运行结果能够看到,tsconfig.app.json 配置文件和 tsconfig.spec.json 配置文件都继承了 tsconfig.base.json 配置文件中的 target 编译选项。

使用非相对路径

extends 属性指定的路径不是以 ./../ 作为起始的,那么编译器将在 node_modules 目录下查找指定的配置文件。

编译器首先在 tsconfig.json 配置文件所在目录的 node_modules 子目录下查找,若该目录下包含了指定的配置文件,则使用该配置文件;否则,继续在父级目录下的 node_modules 子目录下查找,直到搜索到系统根目录为止。若最终未能找到指定的配置文件,则产生编译错误。

假设有如下目录结构的工程:

C:\app
|-- node_modules
|   `-- tsconfig
|       `-- tsconfig.standard.json
|-- index.ts
`-- tsconfig.json

tsconfig.json 配置文件的内容如下:

{
    "extends": "tsconfig/tsconfig.standard.json"
}

此例中,编译器查找 tsconfig/tsconfig.standard.json 文件的步骤如下:

  1. 查找 C:\app\node_modules\tsconfig\tsconfig.standard.json 文件。

  2. 查找 C:\node_modules\tsconfig\tsconfig.standard.json 文件。

  3. 报错,文件未找到。

当编译器找到了匹配的配置文件时就会终止查找过程。此例中,在第 1 步找到了匹配的 tsconfig.standard.json 配置文件,于是使用该配置文件来编译工程并终止后续的查找。