Skip to content
目录

配置篇

配置详情

详细配置

js
{
  "compilerOptions": {
    /* Basic Options */
    "target": "es5" /* target用于指定编译之后的版本目标: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */,
    "module": "commonjs" /* 用来指定要使用的模块标准: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
    "lib": ["es6", "dom"] /* lib用于指定要包含在编译中的库文件 */,
    "allowJs": true,                       /* allowJs设置的值为true或false,用来指定是否允许编译js文件,默认是false,即不编译js文件 */
    "checkJs": true,                       /* checkJs的值为true或false,用来指定是否检查和报告js文件中的错误,默认是false */
    "jsx": "preserve",                     /* 指定jsx代码用于的开发环境: 'preserve', 'react-native', or 'react'. */
    "declaration": true,                   /* declaration的值为true或false,用来指定是否在编译的时候生成相应的".d.ts"声明文件。如果设为true,编译每个ts文件之后会生成一个js文件和一个声明文件。但是declaration和allowJs不能同时设为true */
    "declarationMap": true,                /* 值为true或false,指定是否为声明文件.d.ts生成map文件 */
    "sourceMap": true,                     /* sourceMap的值为true或false,用来指定编译时是否生成.map文件 */
    "outFile": "./",                       /* outFile用于指定将输出文件合并为一个文件,它的值为一个文件路径名。比如设置为"./dist/main.js",则输出的文件为一个main.js文件。但是要注意,只有设置module的值为amd和system模块时才支持这个配置 */
    "outDir": "./",                        /* outDir用来指定输出文件夹,值为一个文件夹路径字符串,输出的文件都将放置在这个文件夹 */
    "rootDir": "./",                       /* 用来指定编译文件的根目录,编译器会在根目录查找入口文件,如果编译器发现以rootDir的值作为根目录查找入口文件并不会把所有文件加载进去的话会报错,但是不会停止编译 */
    "composite": true,                     /* 是否编译构建引用项目  */
    "incremental": true,                   /* Enable incremental compilation */
    "tsBuildInfoFile": "./",               /* Specify file to store incremental compilation information */
    "removeComments": true,                /* removeComments的值为true或false,用于指定是否将编译后的文件中的注释删掉,设为true的话即删掉注释,默认为false */
    "noEmit": true,                        /* 不生成编译文件,这个一般比较少用 */
    "importHelpers": true,                 /* importHelpers的值为true或false,指定是否引入tslib里的辅助工具函数,默认为false */
    "downlevelIteration": true,            /* 当target为'ES5' or 'ES3'时,为'for-of', spread, and destructuring'中的迭代器提供完全支持 */
    "isolatedModules": true,               /* isolatedModules的值为true或false,指定是否将每个文件作为单独的模块,默认为true,它不可以和declaration同时设定 */

    /* Strict Type-Checking Options */
    "strict": true /* strict的值为true或false,用于指定是否启动所有类型检查,如果设为true则会同时开启下面这几个严格类型检查,默认为false */,
    "noImplicitAny": true,                 /* noImplicitAny的值为true或false,如果我们没有为一些值设置明确的类型,编译器会默认认为这个值为any,如果noImplicitAny的值为true的话。则没有明确的类型会报错。默认值为false */
    "strictNullChecks": true,              /* strictNullChecks为true时,null和undefined值不能赋给非这两种类型的值,别的类型也不能赋给他们,除了any类型。还有个例外就是undefined可以赋值给void类型 */
    "strictFunctionTypes": true,           /* strictFunctionTypes的值为true或false,用于指定是否使用函数参数双向协变检查 */
    "strictBindCallApply": true,           /* 设为true后会对bind、call和apply绑定的方法的参数的检测是严格检测的 */
    "strictPropertyInitialization": true,  /* 设为true后会检查类的非undefined属性是否已经在构造函数里初始化,如果要开启这项,需要同时开启strictNullChecks,默认为false */
   "noImplicitThis": true,                /* 当this表达式的值为any类型的时候,生成一个错误 */
    "alwaysStrict": true,                  /* alwaysStrict的值为true或false,指定始终以严格模式检查每个模块,并且在编译之后的js文件中加入"use strict"字符串,用来告诉浏览器该js为严格模式 */

    /* Additional Checks */
    "noUnusedLocals": true,                /* 用于检查是否有定义了但是没有使用的变量,对于这一点的检测,使用eslint可以在你书写代码的时候做提示,你可以配合使用。它的默认值为false */
    "noUnusedParameters": true,            /* 用于检查是否有在函数体中没有使用的参数,这个也可以配合eslint来做检查,默认为false */
    "noImplicitReturns": true,             /* 用于检查函数是否有返回值,设为true后,如果函数没有返回值则会提示,默认为false */
    "noFallthroughCasesInSwitch": true,    /* 用于检查switch中是否有case没有使用break跳出switch,默认为false */

    /* Module Resolution Options */
    "moduleResolution": "node",            /* 用于选择模块解析策略,有'node'和'classic'两种类型' */
    "baseUrl": "./",                       /* baseUrl用于设置解析非相对模块名称的基本目录,相对模块不会受baseUrl的影响 */
    "paths": {},                           /* 用于设置模块名称到基于baseUrl的路径映射 */
    "rootDirs": [],                        /* rootDirs可以指定一个路径列表,在构建时编译器会将这个路径列表中的路径的内容都放到一个文件夹中 */
    "typeRoots": [],                       /* typeRoots用来指定声明文件或文件夹的路径列表,如果指定了此项,则只有在这里列出的声明文件才会被加载 */
    "types": [],                           /* types用来指定需要包含的模块,只有在这里列出的模块的声明文件才会被加载进来 */
    "allowSyntheticDefaultImports": true,  /* 用来指定允许从没有默认导出的模块中默认导入 */
    "esModuleInterop": true /* 通过为导入内容创建命名空间,实现CommonJS和ES模块之间的互操作性 */,
    "preserveSymlinks": true,              /* 不把符号链接解析为其真实路径,具体可以了解下webpack和nodejs的symlink相关知识 */

    /* Source Map Options */
    "sourceRoot": "",                      /* sourceRoot用于指定调试器应该找到TypeScript文件而不是源文件位置,这个值会被写进.map文件里 */
    "mapRoot": "",                         /* mapRoot用于指定调试器找到映射文件而非生成文件的位置,指定map文件的根路径,该选项会影响.map文件中的sources属性 */
    "inlineSourceMap": true,               /* 指定是否将map文件的内容和js文件编译在同一个js文件中,如果设为true,则map的内容会以//# sourceMappingURL=然后拼接base64字符串的形式插入在js文件底部 */
    "inlineSources": true,                 /* 用于指定是否进一步将.ts文件的内容也包含到输入文件中 */

    /* Experimental Options */
    "experimentalDecorators": true /* 用于指定是否启用实验性的装饰器特性 */
    "emitDecoratorMetadata": true,         /* 用于指定是否为装饰器提供元数据支持,关于元数据,也是ES6的新标准,可以通过Reflect提供的静态方法获取元数据,如果需要使用Reflect的一些方法,需要引入ES2015.Reflect这个库 */
  }
  "files": [], // files可以配置一个数组列表,里面包含指定文件的相对或绝对路径,编译器在编译的时候只会编译包含在files中列出的文件,如果不指定,则取决于有没有设置include选项,如果没有include选项,则默认会编译根目录以及所有子目录中的文件。这里列出的路径必须是指定文件,而不是某个文件夹,而且不能使用* ? **/ 等通配符
  "include": [],  // include也可以指定要编译的路径列表,但是和files的区别在于,这里的路径可以是文件夹,也可以是文件,可以使用相对和绝对路径,而且可以使用通配符,比如"./src"即表示要编译src文件夹下的所有文件以及子文件夹的文件
  "exclude": [],  // exclude表示要排除的、不编译的文件,它也可以指定一个列表,规则和include一样,可以是文件或文件夹,可以是相对路径或绝对路径,可以使用通配符
  "extends": "",   // extends可以通过指定一个其他的tsconfig.json文件路径,来继承这个配置文件里的配置,继承来的文件的配置会覆盖当前文件定义的配置。TS在3.2版本开始,支持继承一个来自Node.js包的tsconfig.json配置文件
  "compileOnSave": true,  // compileOnSave的值是true或false,如果设为true,在我们编辑了项目中的文件保存的时候,编辑器会根据tsconfig.json中的配置重新生成文件,不过这个要编辑器支持
  "references": [],  // 一个对象数组,指定要引用的项目
}

文件选项

我们在初始篇中有简单介绍过 tsconfig.json 文件,这里再回顾一下。

回顾

如果一个目录下存在一个 tsconfig.json 文件,那么它意味着这个目录是 TypeScript 项目的根目录。tsconfig.json 文件中指定了用来编译这个项目的根文件和编译选项。 一个项目可以通过以下方式之一来编译:

  • 不带任何输入文件的情况下调用 tsc,编译器会从当前目录开始去查找 tsconfig.json文 件,逐级向上搜索父目录。
  • 不带任何输入文件的情况下调用 tsc,且使用命令行参数 --project(或 -p )指定一个包含 tsconfig.json 文件的目录。

当命令行上指定了输入文件时,tsconfig.json 文件会被忽略。

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

files

它的含义是编译器需要编译的相对或绝对文件路径的单个文件列表。

json
{
  "files": ["src/index.ts"]
}

这时执行 tsc 命令,编译器会编译 src/index.ts 文件。

include

它的含义是编译器需要编译的文件或者目录。

json
{
  "include": ["src"]
}

这时执行 tsc 命令,编译器会编译 src 目录下的所有 ts 文件。

exclude

它的含义是编译器需要排除的文件或者目录。默认会排除 node_modules 目录下的所有文件。

json
{
  "exclude": ["src/lib"]
}

TIP

  1. 如果 filesincludes 都没有指定,编译器默认包含当前目录下所有的 ts 文件。(.ts.d.ts.tsx
  2. 如果 exclude 存在,exclude 配置优先级高于 filesincludes 配置
  3. excludeincludes 配置支持 glob 通配符:*?**

extends

我们可以把一些配置抽离出一个配置文件,再 tsconfig.json 文件引入,方便以后管理与维护。

json
// tsconfig.json

{
  "extends": "./base.json"
}

在主配置文件中,设置文件选项会覆盖调继承文件中的相同的配置项。

compileOnSave

它可以让 IDE 在保存文件时,编译器自动编译。

json
{
  "compileOnSave": true
}

目前只有个别 IDE 支持。

编译选项

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

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

json
{
  "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

打印编译信息。

bash
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

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

module

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

outFile

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

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

ts
// ./src/index.ts
import a = require('./amd');

let str: string = 'abc';
ts
// ./src/amd.ts

let amd: number = 0;

export = amd;

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

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

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

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 函数。先看下面示例:

ts
class B {}

class A extends B {}

export = A;

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

js
'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 之后。编译后的结果如下:

js
'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 函数,文件必须是模块。编译结果如下:

js
'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 语法:

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

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

js
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,alwaysStrictnoImplicitAnystrictNullChecksstrictFunctionTypesstrictPropertyInitializationstrictBindCallApplynoImplicitThis 选项默认都为 true。

alwaysStrict

在代码中注入 use strict

noImplicitAny

不允许隐式的 any 类型。

strictNullChecks

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

strictFunctionTypes

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

strictPropertyInitialization

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

strictBindCallApply

严格的 bindcallapply 检查。

ts
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 类型。

ts
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

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

  • classic 模块解析策略

适用于 AMDSystemES2015

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

ts
// /root/src/moduleA.ts

import { b } from './moduleB';

/**
 * /root/src/moduleB.ts
 * /root/src/moduleB.d.ts
 */

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

ts
// /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 模块解析策略

使用相对方式导入

ts
// /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
 */

使用非相对方式导入

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

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

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

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

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

listEmittedFiles

打印输出的文件。

listFiles

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

解决 vscode 异常提示问题

本节会列举使用 vscode 进行 ts 开发时,出现的异常问题该如何解决。

隐式 any 类型

错误提示:Parameter 'xxx' implicitly has an 'any' type.ts(7006)

  • 解决方案
  1. 修改 tsconfig.json 配置文件,将 noImplicitAny 修改为 false.
json
{
  "noImplicitAny": false
}
  1. 全局安装 tslint 扩展包
bash
$ npm install -g tslint

再安装 vscode 插件 TSLint(deprecated)

this 隐式具有 any 类型

错误提示:'this' implicitly has type 'any' because it does not have a type annotation.ts(2683)

ts
const fn = (a) => {
  return function () {
    return a.apply(this, arguments);
  };
};
  • 解决方案
  1. 添加 this: any
ts
const fn = (a) => {
  return function (this: any) {
    return a.apply(this, arguments);
  };
};
  1. 修改 tsconfig.json 配置文件,将 noImplicitThis 修改为 false.
json
{
  "noImplicitThis": false
}

Cannot write file ... because it would overwrite input file

https://github.com/Microsoft/TypeScript/issues/14538

  • 解决方案
  1. 注销掉 allowJs 或设置为 false,不允许编译 JS 文件(js、jsx)
json
{
  "compilerOptions": {
    ...

    // "allowJs": true,

    ...
  }
}

若想允许编译 JS 文件,参考第二种解决办法

  1. tsconfig 设置 allowJsnoEmit
json
{
  "compilerOptions": {
    ...

    "allowJs": true,
    "noEmit": true,

    ...
  }
}

noEmit 设置为 true 可能会导致 webpack 进行编译打包时报错,可以采用第三种的解决办法.

  1. tsconfig 设置 includeexclude
json
{
  "compilerOptions": {
    ...

    "allowJs": true,
    // "noEmit": true,

    ...
  },
  "include": ["src/**/*.*"],
  "exclude": ["node_modules", "build", "dist"]
}

这里主要是 include 起作用,本来设置其中一个就可以,但 exclude 并没有作用,可能是个bug.