Appearance
allowUmdGlobalAccess 允许Umd全局访问
当设置为 true,allowUmdGlobalAccess 允许你从模块文件内部访问作为全局变量的UMD导出。一个模块文件是用于imports &| exports 的文件。如果不使用这个选项,使用UMD模块的导出,需要一个import声明。
使用这个配置的一个例子是在web项目中,你知道特定的库(比如 jQuery | Lodash) 将总是在运行时可访问到,但你不同通过import方式访问。
baseUrl 👍
允许你设置基础目录来解析非绝对模块名。
你可以定义一个用于做绝对文件解析的根文件夹。
🌰:
bash
baseUrl
├── ex.ts
├── hello
│ └── world.ts
└── tsconfig.json在此项目中使用 "baseUrl": "./",TS将从与 tsconfig.json 相同的文件夹开始的文件进行查找。
typescript
import { helloWorld } from 'hello/world'
console.log(helloWorld)如果你厌倦了类似 '../' 或 ./ 这种导入方式,或需要当你移动文件时需要改变它们,这是一个好的方式来修复这些问题。
module 👍
设置程序的模块系统。可查看 Modules 页面指南获取更多信息。对于Node项目,你很有可能将其设置为 "CommonJS"。
改变 module 会影响到 moduleResolution,可查看 moduleResolution 手册。
下面示例是这个文件的输出:
typescript
// @filename: index.ts
import { valueOfPi } from "./constants";
export const twoPi = valueOfPi * 2;1️⃣ CommonJS
js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.twoPi = void 0;
const constants_1 = require("./constants");
exports.twoPi = constants_1.valueOfPi * 2;2️⃣ UMD
js
(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;
});3️⃣ AMD
js
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;
});4️⃣ System
js
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);
}
};
});5️⃣ ESNext
js
import { valueOfPi } from "./constants";
export const twoPi = valueOfPi * 2;6️⃣ ES2020
js
import { valueOfPi } from "./constants";
export const twoPi = valueOfPi * 2;7️⃣ ES2015/ES6
js
import { valueOfPi } from "./constants";
export const twoPi = valueOfPi * 2;TIP
如果你疑惑 ES2015(即 ES6) 和 ES2020的区别是什么?
ES2020支持动态import,以及import.meta
8️⃣ node16/nodenext(nightly builds)
从 TS4.7+开始,node16 和 nodenext 模式集成到Node的 原生ESM支持。生成的JS文件是 CommonJS 还是 ES2020 取决于文件扩展名以及其最近的 package.json 中设置的 type 值相关。模块解析作用也不同。可以通过 esm-node handbook 了解更多。
9️⃣ None
js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.twoPi = void 0;
const constants_1 = require("./constants");
exports.twoPi = constants_1.valueOfPi * 2;TIP
默认:如果 target 是 ES3 | ES5 则默认是 CommonJS;否则则是 ES2015。
允许值:
- none
- commonjs
- amd
- umd
- systm
- es6/es2015
- es2020
- es2022
- esnext
- node16
- nodenext
相关联配置:
moduleResolution 模块解析
指定模块解析策略:
node针对Node.js的CommonJS实现node12|nodenext针对 Node.js的ESM支持,🚨 需TS4.5+classic用于TS1.6之前。可能不需要在现代代码中使用classic
可查看 moduleResolution 手册。
TIP
默认:如果 module 是 AMD | UMD | System | ES6 | esnext,则使用 classic;如果module是 node12 | nodenext,则默认是 node
允许值:
classicnodenode16nodenext
相关联配置:
可以看出其实只有2种解析方案 classic | node 相关的
moduleSuffixes - 模块后缀
提供一种方法,以覆盖解析模块时要搜索的文件名后缀的默认列表。
json
{
"compilerOptions": {
"moduleSuffixes": [".ios", ".native", ""]
}
}基于上面配置,如下导入:
typescript
import * as foo from './foo'TS会查找相对文件 ./foo.ios.ts , ./foo.native.ts,和最后的 ./foo.ts。
WARNING
🚨 moduleSuffixes 中最后的空字符 '' 对TS用来查找 ./foo.ts 是必须的。
这个功能对于React Native项目,每个目标平台使用包含不同 moduleSuffixes的不同的tsconfig.json文件有用。
noResolve - 不解析
默认情况下,TS会检查import和<reference指令的初始文件集,把将这些解析的文件添加到你的程序中。
如果设置了 noResolve,上面过程不会发生。但是,import 语句仍会被检测是否解析到了一个有效的模块,所以你需要用其他方法来满足这个要求😅。
paths 👍
一系列条目,它们将导入重新映射到相对于 baseUrl 的查找位置。(译者注:多用于设置import别名)。path-mapping - handbook 有很大一块讲解 paths 的用法。
paths 让你声明TS该如何解析 require|imports 的导入。
🌰:
json
{
"compilerOptions": {
"baseUrl": ".", // 🚨如果使用 `paths`,则必须声明baseUrl选项
"path": {
// 这个映射是相对于 `baseUrl` 的
"jquery": ["node_modules/jquery/dist/jquery"]
}
}
}你可以直接使用 import jquery,并且本地获得所有正确的类型😎。
🌰:
json
{
"compilerOptions": {
"baseUrl": "src", // 注意这里的baseUrl设置未了 `src`
"path": {
"app/*": ["app/*"],
"config/*": ["app/_config/*"],
"environment/*": ["environments/*"],
"shared/*": ["app/_shared/*"],
"helpers/*": ["helpers/*"],
"tests/*": ["tests/*"]
}
}
}这种情况,你告诉TS文件解析器支持一些自定义前缀来查找代码。这个模式用于避免项目中过长的相对路径🤩。
resolveJsonModule - 解析JSON模块
允许引入 .json 扩展的模块,这在Node项目中很常见。这包括根据静态 JSON 形状为导入生成类型。
🚨 TS默认是不支持解析JSON文件的:
typescript
// @filename: settings.json
🚫Cannot find module './settings/json'. Consider using '--resolveJsonModule'
to import module with '.json' extension.
{
"repo": "TypeScript",
"dry": false,
"debug": false
}
// @filename: index.ts
import settings from "./settings.json";
settings.debug === true;
settings.dry === 2;开启这个选项后,允许导入JSON,并验证JSON文件类型:
typescript
// @filename: settings.json
{
"repo": "TypeScript",
"dry": false,
🚫This condition will always return 'false' since the types
'boolean' and 'number' have no overlap.
"debug": false
}
// @filename: index.ts
import settings from "./settings.json";
settings.debug === true;
settings.dry === 2;rootDir 👍
默认:所有非声明输入文件的最长公共路径。如果设置了 composite,默认是包含 tsconfig.json 文件的目录。
当TS编译文件时,它会在输出目录中保留与输入目录中相同的目录结构。
比如,假设下面输入文件:
bash
MyProj
├── tsconfig.json
├── core
│ ├── a.ts
│ ├── b.ts
│ ├── sub
│ │ ├── c.ts
├── types.d.tsrootDir 的推断之是所有非声明输入文件的最长公共路径,这个例子的最长公共路径是 core/。
如果你的 outDir (输出目录)是 dist,TS输出结果为:
bash
MyProj
├── dist
│ ├── a.js
│ ├── b.js
│ ├── sub
│ │ ├── c.js但是,你可能有意将 core 作为输出目录结构的一部分。通过在tsconfig.json中设置 rootDir: ".",TS会返回如下输出目录结构:
bash
MyProj
├── dist
│ ├── core # core 得以保留
│ │ ├── a.js
│ │ ├── b.js
│ │ ├── sub
│ │ │ ├── c.js🚨
请注意,TS永远不会将输出文件写入 outDir 之外的目录,并且永远不会跳过生成文件。正因如此,rootDir 也强制所有需要被生成的文件都要在 rootDir 路径之下。
比如,假设你有如下结构:
bash
MyProj
├── tsconfig.json
├── core
│ ├── a.ts
│ ├── b.ts
├── helpers.ts如果tsconfig.json配置如下,就会报错:
json
{
"compilerOptions": {
"rootDir": "core"
},
"include": ["*"]
}因为它导致文件(helper.ts) 被生成在 outDir 外(比如:../helper.js)😅。
TIP
默认:从输入文件列表中计算
rootDirs 🤔
所有 rootDirs,你可以通知编译器,有很多 虚拟的 目录充当单个根(root)。这允许编译器解析这些“虚拟”目录中的相对模块导入,就好像它们被合并到一个目录中一样🤔。
比如:
bash
src
└── views
└── view1.ts (can import "./template1", "./view2`)
└── view2.ts (can import "./template1", "./view1`)
generated
└── templates
└── views
└── template1.ts (can import "./view1", "./view2")tsconfig.json:
json
{
"compilerOptions": {
"rootDirs": ["src/views", "generated/templates/views"]
}
}这不会影响TS生成JS,它只是模拟了这样一个假设,即它们将能够在运行时通过这些相对路径工作。
rootDirs 可用于为非 TS 或 JS 的文件提供单独的“类型层(type layer)”,方法是在另一个文件夹中为生成的 .d.ts 文件提供主目录。
这个技术对于打包的应用包含非必需代码的 import 文件有用:
bash
src
└── index.ts
└── css
└── main.css
└── navigation.css
generated
└── css
└── main.css.d.ts
└── navigation.css.d.tstsconfig.json:
json
{
"compilerOptions": {
"rootDirs": ["src", "generated"]
}
}这种技术可以让你提前为非代码源文件生成类型。😎
然后,导入会根据源文件的位置自然地工作。比如,./src/index.ts 可以导入 ./src/css/main.css 文件,然后TS将根据生成的 .d.ts文件意识到打包器对该文件类型的行为。
typescript
// @filename: index.ts
import { appClass } from "./main.css";typeRoots - 类型根
默认情况下,所有可见的 @types packages都将包含在你的编译中。在 node_modules/@types 中任何闭合文件夹都被认为是 可见的(visible) 包。比如,这意味着 ./node_modules/@types/ , ../node_modules/@types/ & ../node_modules/@types/ 等等。
如果指定了 typeRoots, 只有在 typeRoots 下的包(packages)才被包含。比如:
json
{
"compilerOptions": {
"typeRoots": ["./typings", "./vendor/types"]
}
}这个配置文件将包含所有在 ./typings & ./vendor/types 下的所有包,而不包含 ./node_modules/@types 下的包。所有路径都是相对于 tsconfig.json 的。
types 👍
默认情况下,所有可见的 @types packages都将包含在你的编译中。在 node_modules/@types 中任何闭合文件夹都被认为是 可见的(visible) 包。比如,这意味着 ./node_modules/@types/ , ../node_modules/@types/ & ../node_modules/@types/ 等等。
如果指定了 types,只有列举了的包才会包含到全局作用域中。
比如:
json
{
"compilerOptions": {
"types": ["node", "jest", "express"]
}
}👩🏫 这个 tsconfig.json 将 只 包含 ./node_modules/@types/node & ./node_modules/@types/jest & ./node_modules/@types/express。其余在 ./node_modules/@types/* 下的包将不会被包含。
这有什么影响呢?
这个配置不会影响 @types/* 如何被包含在你的应用代码中,比如,如果你有如上的编译选项,代码如下:
typescript
import * as moment from 'moment'
moment().format("MMMM Do YYYY, h:mm:ss a");这个 moment 导入也是具有完全类型的。
当你设置了这个选项,通过不包含某个模块到 types 数组中:
- 将不会添加全局到你的项目中(比如 node中的
process,Jest中的expect)😅 - 将不会将导出显示为自动导入推荐
这个功能和 typeRoots 的区别在于:它是只指定你想包含的确切类型,而 typeRoots 支持你想要特定的文件夹。
💡
相关联配置:
typeRoots
原文档:
2022年08月19日00:14:46