files
需要解析的ts
的文件。
{
"files": ["./index.ts"]
}
当找不到对应的文件时会报错。
extends
用于继承另一个tsconfig.json
文件的配置。
// base.json
{
"extends": "./src/tsconfig"
}
// tsconfig.json
{
"compilerOptions": {
"target": "es6"
},
"files": ["./index.ts"]
}
先加载base.json
,之后读取tsconfig.json
的配置,将ts
解析成es6
的js
文件。
include
指定需要编译处理的文件列表,支持 glob 模式匹配,文件的解析路径相对于当前项目的 tsconfig.json 文件位置
这里要注意,如果指定了 files 选项值,则 includes 的默认值为[]
,否则默认包含当前项目中所有文件["**/*"]
{
"include": ["index.ts", "src/**/*"]
}
上面这个例子解析了与tsconfig.json
文件同目录的index.ts
文件以及src
目录下的所有ts
文件。
include
和exclude
都支持使用通配符:
*
: 匹配零个或者多个字符(包括目录的分隔符)?
: 匹配任一字符(包括目录分隔符)**/
: 匹配任何层级的嵌套目录在使用 glob
模式匹配时,如果没有明确指定文件扩展名。那么默认情况下仅会包含.ts
、.tsx
和.d.ts
类型的文件。但是如果allowJs
选项被设置成了true
,那么.js
和.jsx
文件也会被包含其中。
exclude
用于指定当解析include
选项时,需要忽略的文件列表
首先要注意,exclude
的默认值是["node_modules", "bower_components", "jspm_packages"]
加上outDir
选项指定的值。因此下面的示例中,虽然没有明确指定exclude
选项值,但它的的值依然为["node_modules", "bower_components", "jspm_packages", "dist"]
{
"include": ["index.ts", "src/**/*"],
"exclude": ["src/**/*"]
}
上面的配置不解析src
目录下的所有ts
文件。
其次要注意的是,exclude
只会对include
的解析结果有影响。又因为include
的默认值为["**/*"]
,即全部文件。所以,当没有明确指定include
选项值时,exclude
中指定的就是直接忽略当前项目中的文件。
而且,即使在exclude
中指定的被忽略文件,还是可以通过import
操作符、types
操作符、///
files
选项中添加配置的方式对这些被忽略的代码文件进行引用的。
files
用来指定需要编译的文件列表(注意,只能是文件,不能是文件夹)。
{
"files": ["index.ts", "src/"]
}
上面的配置会报错,因为不能配置目录。
这个配置项适用于想要指定的文件数量比较少,并且不需要使用 glob
模式匹配的情况。否则,请使用 include
配置项。
references
指定工程引用依赖。
在项目开发中,有时候为了方便将前端项目和后端
node
项目放在同一个目录下开发,两个项目依赖同一个配置文件和通用文件,但我们希望前后端项目进行灵活的分别打包,那么我们可以进行如下配置:
Project
- src
- client //客户端项目
- index.ts // 客户端项目文件
- tsconfig.json // 客户端配置文件
{
"extends": "../../tsconfig.json", // 继承基础配置
"compilerOptions": {
"outDir": "../../dist/client", // 指定输出目录
},
"references": [ // 指定依赖的工程
{"path": "./common"}
]
}
- common // 前后端通用依赖工程
- index.ts // 前后端通用文件
- tsconfig.json // 前后端通用代码配置文件
{
"extends": "../../tsconfig.json", // 继承基础配置
"compilerOptions": {
"outDir": "../../dist/client", // 指定输出目录
}
}
- server // 服务端项目
- index.ts // 服务端项目文件
- tsconfig.json // 服务端项目配置文件
{
"extends": "../../tsconfig.json", // 继承基础配置
"compilerOptions": {
"outDir": "../../dist/server", // 指定输出目录
},
"references": [ // 指定依赖的工程
{"path": "./common"}
]
}
- tsconfig.json // 前后端项目通用基础配置
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"strict": true,
"composite": true, // 增量编译
"declaration": true
}
}
这样配置以后,就可以单独的构建前后端项目。
前端项目构建
tsc -v src/client
后端项目构建
tsc -b src/server
输出目录
Project
- dist
- client
- index.js
- index.d.ts
- common
- index.js
- index.d.ts
- server
- index.js
- index.d.ts
compilerOptions
主要用于配置编译选项。
若 compilerOptions
属性被忽略,则编译器会使用默认值。
allowUnreachableCode
是否允许报告执行不到的代码错误,默认值为undefined
,在编辑器上提示警告。
function fn(n: number) {
if (n > 5) {
return true;
} else {
return false;
}
return true;
}
当设置为false
,编译会提示Unreachable code detected
错误。
allowUnusedLabels
是否允许报告未使用的标签错误。默认值为undefined
,在编辑器上提示警告。
标签在js
中很少见,通常表示试图写入对象文字。
function verifyAge(age: number) {
// Forgot 'return' statement
if (age > 18) {
verified: true;
// 上面这行会提示警告
}
}
当设置为false
,编译会提示Unused label
错误。
alwaysStrict
是否讲文件被解析成严格模式(strict mode
)。默认为false
。
在生成的js
文件的第一行都有use strict
字段。
noImplicitAny
是否需要显示的声明变量的类型any
。默认false
在某些场景中,有些变量我们没有声明类型,typescript
会默认为any
。
// 没有设置s的类型
function fn(s) {
// 当我们传入非string类型时会报错
console.log(s.subtr(3));
}
fn(42);
当设置true
时,编译会报错提示我们应该为s
设置一个any
类型。
noImplicitOverride
在类的继承中使用。默认false
。
class Album {
download() {
// 默认行为
}
}
class SharedAlbum extends Album {
download() {
// 覆写
}
}
如果不熟悉父类,会很容易搞混是子类的方法还是覆写父类的方法,当设置为true
时,如果没有在覆写的方法前添加override
关键字,会提示报错,这样可以很明显进行区分。
class Album {
setup() {}
}
class MLAlbum extends Album {
override setup() {}
}
class SharedAlbum extends Album {
setup() {}
// 报错 This member must have an 'override' modifier because it overrides a member in the base class 'Album'.
}
noImplicitReturns
是否需要函数的每个分支都会有返回值。默认false
function lookupHeadphonesManufacturer(color: "blue" | "black"): string {
if (color === "blue") {
return "beats";
} else {
("bose");
}
}
// 当设置为true时会报错 Not all code paths return a value.
noImplicitThis
是否允许this
有隐式的any
类型,默认false
。
class Rectangle {
width: number;
height: number;
constructor(width: number, height: number) {
this.width = width;
this.height = height;
}
getAreaFunction() {
return function () {
return this.width * this.height;
};
}
}
在上面的getAreaFunction
方法中返回一个方法,内部使用到this
并不是Rectangle
的实例,typescript
会默认this
为any
,当设置为true
时会报错。
noPropertyAccessFromIndexSignature
确保通过“点”(obj.key
)语法和“索引”(obj["key"]
)访问字段与在类型中声明属性的方式之间的一致性。
如果没有设置字段,对于未声明的属性,我们也可以通过点去访问:
interface GameSettings {
speed: "fast" | "medium" | "slow";
quality: "high" | "low";
// 自定义属性
[key: string]: string;
}
function getSettings(): GameSettings {
return {
speed: "fast",
quality: "high",
brand: "ford",
};
}
const gs = getSettings();
// 当noPropertyAccessFromIndexSignature设置为true时通过点访问自定义属性会报错,只能通过索引访问
gs.brand;
gs["brand"];
noUnusedLocals
是否不允许存在声明了却未使用的变量,默认false
function log() {
const a = 1;
return 1;
}
当设置为true
时,会报错。
noUnusedParameters
是否不允许存在声明了却未使用的参数,默认false
function log(b) {
const a = 1;
return 1;
}
strict
是否开启所有严格的类型检查。
strictBindCallApply
设置后,typescript
会检查函数的call
,bind
,apply
方法中接受的参数类型。默认true
。
function fn(x: string) {
return parseInt(x);
}
const n1 = fn.call(undefined, "10");
// 当设置strictBindCallApply为false不会报错
const n2 = fn.call(undefined, false);
strictFunctionTypes
开启此选项会启用严格的函数类型检查。
const foo = (a: string) => {
console.log(a);
};
interface Bar {
(a: string | string[]): void;
}
// 开启 compilerOptions.strictFunctionTypes, 报错
// Type '(a: string) => void' is not assignable to type 'Bar'.
const bar: Bar = foo;
需要将Bar
修改成与foo
同样的类型
interface Bar {
(a: string): void;
}
strictNullChecks
开启此选项让typescript
执行严格的null
检查。
const foo: string | null | undefined = undefined;
// 不开启 compilerOptions.strictNullChecks ,不会有编译时错误,但是运行时会出现异常(Cannot read properties of undefined )
// 开启 compilerOptions.strictNullChecks,会出现编译时错误(Object is possibly 'undefined')
console.log(foo.length);
exactOptionalPropertyTypes
开启此选项, typescript
会对可空属性执行更严格的类型检查, 可空属性只有在初始化时可以留空为undefined
, 但是不能被手动设置为undefined
。
例如有一个IFoo
接口
interface IFoo {
foo?: string;
}
在默认情况(false
)下,下面的代码没问题。
const obj: IFoo = {};
obj.foo = "1111";
console.log(obj.foo);
obj.foo = undefined;
console.log(obj.foo);
但是当设置了exactOptionalPropertyTypes
为true
后,编译就会报错
const obj: IFoo = {};
obj.foo = "1111";
console.log(obj.foo);
// 编译器会报: Type 'undefined' is not assignable to type 'string' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the type of the target.
obj.foo = undefined;
console.log(obj.foo);
// 这一行会报: Type '{ foo: undefined; }' is not assignable to type 'IFoo' with 'exactOptionalPropertyTypes: true'.
const obj2: IFoo = {
foo: undefined,
};
strictPropertyInitialization
开启此选项让typescript
严格的对象属性初始化检查,在类中定义的属性必须在构造函数中初始化。
class Foo {
// Property 'foo' has no initializer and is not definitely assigned in the constructor.
foo: string;
}
// 需改成这样
class Foo {
foo: string;
constructor() {
this.foo = "";
}
}
useUnknownInCatchVariables
baseUrl
解析非相对模块的基地址,默认是当前目录
baseUrl
├── ex.ts
├── hello
│ └── world.ts
└── tsconfig.json
设置baseUrl: './'
// 在文件引入模块就不需要携带
import { helloWorld } from "hello/world";
console.log(helloWorld);
module
指定生成代码的模板标准
例子:
import { valueOfPi } from "./constants";
export const twoPi = valueOfPi * 2;
commonjs
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.twoPi = void 0;
const constants_1 = require("./constants");
exports.twoPi = constants_1.valueOfPi * 2;
umd
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
} else if (typeof define === "function" && define.amd) {
define(["require", "exports", "./constants"], factory);
}
})(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.twoPi = void 0;
const constants_1 = require("./constants");
exports.twoPi = constants_1.valueOfPi * 2;
});
amd
define(["require", "exports", "./constants"], function (
require,
exports,
constants_1
) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.twoPi = void 0;
exports.twoPi = constants_1.valueOfPi * 2;
});
system
System.register(["./constants"], function (exports_1, context_1) {
"use strict";
var constants_1, twoPi;
var __moduleName = context_1 && context_1.id;
return {
setters: [
function (constants_1_1) {
constants_1 = constants_1_1;
},
],
execute: function () {
exports_1("twoPi", (twoPi = constants_1.valueOfPi * 2));
},
};
});
esnext
import { valueOfPi } from "./constants";
export const twoPi = valueOfPi * 2;
ES2020
import { valueOfPi } from "./constants";
export const twoPi = valueOfPi * 2;
ES2015/ES6
import { valueOfPi } from "./constants";
export const twoPi = valueOfPi * 2;
None
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.twoPi = void 0;
const constants_1 = require("./constants");
exports.twoPi = constants_1.valueOfPi * 2;
moduleResolution
模块解析策略,ts
默认用node
的解析策略,即相对的方式导入
moduleSuffixes
用于覆盖默认的文件后缀解析。
{
"compilerOptions": {
"moduleSuffixes": [".ios", ".native", ""]
}
}
当引入某个文件
import * as foo from "./foo";
typescript
会先查询./foo.ios.ts
,./foo.native.ts
,最后才会查询./foo.ts
。
paths
路径映射
{
"compilerOptions": {
"baseUrl": ".", // 如果需要使用paths,必须声明baseUrl
"paths": {
// 如使用jq时不想使用默认版本,而需要手动指定版本,可进行如下配置
"jquery": ["node_modules/jquery/dist/jquery.min.js"]
}
}
}
resolveJsonModule
开启json
文件引入.
// @filename: settings.json
{
"repo": "TypeScript",
"dry": false,
"debug": false
}
// @filename: index.ts
import settings from "./settings.json";
settings.debug === true;
settings.dry === 2;
rootDir
用来指定编译文件的根目录,编译器会在根目录查找入口文件,如果编译器发现以 rootDir
的值作为根目录查找入口文件时如果没有把所有文件加载进去的话会报错,但是不会停止编译。
MyProj
├── tsconfig.json
├── core
│ ├── a.ts
│ ├── b.ts
│ ├── sub
│ │ ├── c.ts
├── index.ts
设置rootDir: "core"
会报错,因为除了core
目录下还存在index.ts
这个ts
文件。但是并不会停止编译。
outDir
用来指定输出文件夹,值为一个文件夹路径字符串,输出的文件都将放置在这个文件夹。
像rootDir
的例子,设置outDir: 'dist'
,那么会生成一个dist
目录
|── dist
│ ├── a.js
│ ├── b.js
│ ├── sub
│ │ ├── c.js
types
用来指定需要包含的模块,只有在这里列出的模块的声明文件才会被加载进来。
默认情况下,node_modules/@types
目录下的所有类型都是被包含在编译程序中,如果指定了types
,那么只有被指定的类型才会被加载。
{
"compilerOptions": {
"types": ["node", "jest", "express"]
}
}
上面这个配置只会加载./node_modules/@types/node
, ./node_modules/@types/jest
, ./node_modules/@types/express
,node_modules/@types/
目录下的其他类型并不包含。
declaration
用来指定是否在编译的时候生成相应的".d.ts
"声明文件。如果设为true
,编译每个ts
文件之后会生成一个js
文件和一个声明文件。但是declaration
和allowJs
不能同时设为true
。
|── dist
│ ├── a.js
│ ├── a.d.ts
│ ├── b.js
│ ├── b.d.ts
│ ├── sub
│ │ ├── c.js
│ │ ├── c.d.ts
allowJs
来指定是否允许编译 js 文件,默认是false
,即不编译js
文件
declarationDir
用来指定输出声明文件夹,值为一个文件夹路径字符串,输出的声明文件都将放置在这个文件夹。
declarationMap
用于指定是否为声明文件.d.ts
生成map
文件。
emitDeclarationOnly
只生成d.ts
这些声明文件,不生成编译后的js
文件。
importHelpers
指定是否引入tslib
里的辅助工具函数,默认为false
比如下面这个函数
export function fn(arr: number[]) {
const arr2 = [1, ...arr];
}
如果没有设置importHelpers
,那么解析后的js
文件为
"use strict";
var __spreadArray =
(this && this.__spreadArray) ||
function (to, from, pack) {
if (pack || arguments.length === 2)
for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
exports.__esModule = true;
exports.fn = void 0;
function fn(arr) {
var arr2 = __spreadArray([1], arr, true);
}
exports.fn = fn;
解析后为
"use strict";
exports.__esModule = true;
exports.fn = void 0;
var tslib_1 = require("tslib");
function fn(arr) {
var arr2 = tslib_1.__spreadArray([1], arr, true);
}
exports.fn = fn;
importsNotUsedAsValues
用于控制模块加载,有以下 3 个选项:
remove
:默认值,对于引入类型,在解析成js
后会移除模块依赖。perserve
:只要引入了模块,哪怕没有使用,在解析成js
都不会移除该模块。error
:如果只引入了类型,那么会报错,可以将importsNotUsedAsValues
设置成其他值或者通过import type
进行引入。noEmit
不生成文件(js
、声明文件、sourmap
这些)
noEmitOnError
当编译失败时不生产文件,ts
在编译时即使出现异常也是会生成对应的编译文件。
outFile
将多个相互依赖的文件生成一个文件,可以用在 AMD
模块中。
removeComments
移除注释
lib
用于指定要包含在编译中的库文件
target
用于指定编译后js
文件里的语法应该遵循哪个JavaScript
的版本的版本目标: ‘ES3
’ (default
), ‘ES5
’, ‘ES2015
’, ‘ES2016
’, ‘ES2017
’, ‘ES2018
’, ‘ES2019
’ or ‘ESNEXT
’.
listEmittedFiles
用于打印出生成文件的日志。默认成功时没有任何输出。
listFiles
打印出在编译过程中使用了哪些文件(需要编译的文件及相关的类型文件)