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 = "";
}
}
useUnknownInCatchVariablesbaseUrl解析非相对模块的基地址,默认是当前目录
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打印出在编译过程中使用了哪些文件(需要编译的文件及相关的类型文件)