tsconfig配置compilerOptions
前言 tsc编译读取文件规则
定义目录解构
ts-project
├─tsconfig.json
├─src
| ├─index.js
| └index.ts
tsconfig.js
target: es2016
module: commonjs
strict: true
esModuleInterop: true
skipLibCheck: true
forceConsistentCasingInFileNames: true
- 执行编译命令时指定了具体的文件或者文件夹,例如
tsc ./src/index.ts
,则编译器只会读取当前目录下的tsconfig.json
文件,不会一直往上遍历父级目录。 - 如果使用默认命令
tsc / tsc -p tsconfig.json
进行编译,会默认读取上层的tsconfig配置文件
为什么vscode会高亮,因为已经引入声明文件,例如console
compilerOptions 用于控制 TypeScript 编译器如何对 TypeScript 代码进行转换, 按照官方的配置划分进行实践说明。
1. Projects
-
incremental
: 当设置为true
时,TypeScript 编译器将会在编译过程中生成.tsbuildinfo
文件用于后续的增量编译,可以提升编译速度。此选项需要同时开启composite
选项才可以生效。 -
composite
: 当设置为true
时,允许使用 TypeScript 项目引用(Project reference)特性。它允许您将多个子项目组合成一个项目,从而实现更高效的编译和依赖管理。当composite
选项被设置为true
时,同时也需要将所有的子项目的tsconfig.json
中的composite
选项也设置为true
。 -
disableSolutionSearching
: 当设置为true
,在编辑多个 TypeScript 项目时,将不会使用方案搜索。一般情况下,TypeScript 编译器默认会在方案内搜索相关文件,以加快编译速度,但当有很多项目时,这种搜索可能会变得很慢,这个选项的作用就是禁用方案搜索功能。 -
disableReferencedProjectLoad
: 当设置为true
,TypeScript 编译器将不会自动加载引用的项目,这可能会降低编译时间。但需要注意的是,如果设置为true
,则必须手动加载引用的项目。 -
tsBuildInfoFile
: 指定增量编译文件的输出路径。 -
disableReferencedProjectLoad
:如果项目很大,则可以使用标志disableReferencedProjectLoad
禁用所有项目的自动加载。相反,当您通过编辑器打开文件时,项目会动态加载。
2. Language and Environment
2.1 target
"target": "es5" /* target用于指定编译之后的版本目标:
'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'.
如上 index.ts
const arr = [1, 2, 3];
;()=> {
console.log('打印***a', arr)
}
ES3编译结果
ES6编译结果
2.2 lib noLib
如果target为ES3,默认导入ES3的lib,此时想加入其他的用处,需要在lib中额外加入
noLib: 不需要库文件与lib互斥
例如process是node的,需要安装@types/node 会
例如 console.log 是在默认的lib.dom.d.ts中
如果安装了@types/node 会覆盖原有的声明
2.3 jsx、jsxFactory、jsxFragmentFactory、jsxImportSource、reactNamespace
- jsx:控制 JSX 在 JavaScript 文件中的输出方式。 这只影响
.tsx
文件的 JS 文件输出。
react
: 将 JSX 改为等价的对React.createElement
的调用并生成.js
文件。react-jsx
: 改为__jsx
调用并生成.js
文件。react-jsxdev
: 改为__jsx
调用并生成.js
文件。preserve
: 不对 JSX 进行改变并生成.jsx
文件。react-native
: 不对 JSX 进行改变并生成.js
文件。
- jsxFactory:更改使用经典 JSX 运行时编译 JSX 元素时在
.js
文件中调用的函数。最常见的更改是使用"h"
或"preact.h"
,而不是默认的"React.createElement"
(如果使用preact
) - jsxFragmentFactory:指定在目标反应时使用的 JSX 片段工厂函数 JSX 发出与
jsxFactory
编译器选项指定,例如Fragment
。 - jsxImportSource:JSX 导入源
- reactNamespace: 指定用于'createElement'的对象。仅当目标为'react' JSX时适用。
2.4 experimentalDecorators、emitDecoratorMetadata
- experimentalDecorators: true /* 用于指定是否启用实验性的装饰器特性 */
- emitDecoratorMetadata: true, /* 用于指定是否为装饰器提供元数据支持,关于元数据,也是ES6的新标准,可以通过Reflect提供的静态方法获取元数据,如果需要使用Reflect的一些方法,需要引入ES2015.Reflect这个库 */
emitDecoratorMetadata设置为true编译结果不同
2.5 useDefineForClassFields、moduleDetection
- useDefineForClassFields: 使用定义类字段
如果target
为 ES2022 或更高,则为true
,否则包括ESNext
否则为false
- moduleDetection:控制检测模块格式JS文件
"auto"
(默认)- TypeScript 不仅会查找导入和导出语句,还会检查package.json
中的"type"
字段在以module
:nodenext
或node16
运行时是否设置为"module"
,并在jsx
:react-jsx
下运行时检查当前文件是否为 JSX 文件。"legacy"
- 与 4.6 及更早版本的行为相同,使用导入和导出语句来确定文件是否为模块。"force"
- 确保将每个非声明文件视为一个模块。
3.Modules
3.1 module、moduleResolution
设置程序的模块系统.改变 module
可能会影响 moduleResolution
,它也有 一个参考页。
导入导出才用 cmd
amd
umd
esNext
moduleResolution: 指定模块解析策略:'node'
(Node.js) 或 'classic'
(在 TypeScript 1.6 版本之前使用)。 你可能不需要在新代码中使用 classic
。
在使用Node策略时,还需要指定"baseUrl"和"path"属性来告诉编译器如何查找模块。
{
"compilerOptions": {
"moduleResolution": "node",
"baseUrl": "./src",
"paths": {
"app/*": \["template/*", "src/\*"]
}
}
}
"baseUrl"指定在哪里开始查找模块. 是相对路径 ./
,而"paths"指定如何将导入语句中的模块名称映射到实际的文件路径。
import app from 'app/index'
//就是映射到template下的文件,多个可以进行依次寻找
3.2 rootDir
默认: 所有输入的非声明文件中的最长公共路径。若 composite
被指定,则是包含 tsconfig.json
文件的目录。rootDir官网
案例:
当前目录结构:
├─tsconfig.json
├─src
| └index.ts
当指定了outDir为dist,设定rootDir为. 或者 ./
,生成dist目录结构如下:
├─tsconfig.json
├─src
| └index.ts
├─dist
| ├─src
| | └index.js
rootDir修改为../
结构生成如下,会将my-lib作为dist中的文件输出
├─tsconfig.json
├─src
| └index.ts
├─dist
| ├─my-lib
| | ├─src
| | | └index.js
rootDir,可以设置成任意路径吗?设置为./core
,答案是不可以将include设置之外的文件包含进来。
3.3 rootDirs
通过 rootDirs
,你可以告诉编译器有许多“虚拟”的目录作为一个根目录。这将会允许编译器在这些“虚拟”目录中解析相对应的模块导入,就像它们被合并到同一目录中一样。
3.4 typeRoots
默认情况下,所有 可见 的 ”@types
” 包都将包含在你的编译过程中。 在 node_modules/@types
中的任何包都被认为是 可见 的。 例如,这意味着包含 ./node_modules/@types/
,../node_modules/@types/
,../../node_modules/@types/
中所有的包。
当 typeRoots
被指定,仅有 在 typeRoots
下的包会被包含。例如:
{
"compilerOptions": {
"typeRoots": ["./typings", "./vendor/types"]
}
}
这个配置文件将包含 ./typings
和 ./vendor/types
下的所有包,而不包括 ./node_modules/@types
下的。其中所有的路径都是相对于 tsconfig.json
。
3.4 types
默认情况下,所有 可见 的 ”@types
” 包都将包含在你的编译过程中。 在 node_modules/@types
中的任何包都被认为是 可见 的。 例如,这意味着包含 ./node_modules/@types/
,../node_modules/@types/
,../../node_modules/@types/
中所有的包。。
当 types
被指定,则只有列出的包才会被包含在全局范围内。例如:
{
"compilerOptions": {
"types": ["node", "jest", "express"]
}
}
这个 tsconfig.json
文件将 只会 包含 ./node_modules/@types/node
,./node_modules/@types/jest
和 ./node_modules/@types/express
。 其他在 node_modules/@types/*
下的包将不会被包含。
typeRoots:["./src/types"]
"typeRoots": [], /* typeRoots用来指定声明文件或文件夹的路径列表,如果指定了此项,则只有在这里列出的声明文件才会被加载 */
例如使用 process 已经安装了@types/node 重新设置typeRoots路径 则process找不到
上面重新指定types根路径,如果没有,可以使用type进行导入@types中的声明文件
3.5 baseUrl、paths
- baseUrl:设置解析非绝对路径模块名时的基准目录。baseUrl官网 例如:定义一个根目录,以进行绝对路径文件解析。
├─tsconfig.json
├─utils.ts
├─utils
| └utils.ts
├─src
| └index.ts
index.ts中引入
import add from 'utils'
- baseUrl设置为'./',寻找与
tsconfig.json
处于相同目录的文件。
- baseUrl设置为'./utils',寻找与
tsconfig.json
处于相同目录下的utils文件夹下的文件
问题:使用baseUrl,无法编译运行,实际上是告诉 TypeScript 编译器和支持的工具(如编辑器自动补全)在解析非相对模块时使用这个基本目录。它常用于避免过长的相对导入路径,例如 ../../../../utils
这样的导入语句。
解析过程:
- 在 TypeScript 文件中使用
import ... from 'utils'
时,TypeScript 编译器查找与baseUrl
相关的位置。 - TypeScript 编译后,得到的 JavaScript 文件将具有
const ... = require('utils');
这样的 require 语句。可以在上面截图所示 - 当使用 Node.js 运行此转换后的代码时,Node.js 将尝试从
node_modules
文件夹或内置模块加载 'utils',而不是使用 TypeScript 的baseUrl
配置。
要解决这个问题需要给utils单独定义导入的路径映射。
- paths:可以允许你声明 TypeScript 应该如何解析你的
require
/import
,定义文件路径映射
运行ts文件,使用ts-node
,使用 tsconfig-paths
的附加包来处理 paths
选项。
-
安装
tsconfig-paths ts-node
包:npm install --save-dev tsconfig-paths ts-node
-
使用
npx ts-node -r tsconfig-paths/register src/index.ts
运行
3.6 allowUmdGlobalAccess
当 allowUmdGlobalAccess
设置为 true 时,将允许你在模块文件中以全局变量的形式访问 UMD 的导出。 模块文件是具有或同时导入、导出的文件。当未设置这个选项时,使用 UMD 模块的导出需要首先导入声明。
3.7 resolveJsonModule
必须是commonjs设置
设置为true 允许导入扩展名为“.json”的模块,这是节点项目中的常见做法。这包括基于静态 JSON 形状为 import
生成类型。
开启需要设置"esModuleInterop": true,
能正常读取json文件
3.8 noResolve (不使用)
默认情况下,TypeScript 将检查 import
和 <reference
指令的初始文件集,并将这些解析的文件添加到程序中。
设置为true会导致类型丢失和导入错误。这个选项主要用于调试和诊断模块解析过程。
3.9 moduleSuffixes
提供一种方法来覆盖解析模块时要搜索的文件名后缀的默认列表。
"moduleSuffixes": [".ios", ".native", ""]
TypeScript 将查找相关文件 ./foo.ios.ts
、 ./foo.native.ts
4.JavaScript Support
4.1 allowJs、checkJs
如果引入js文件会导致以下错误
如果没有使用var 定义变量会报错
4.2 maxNodeModuleJsDepth
在 node_modules
下搜索并加载 JavaScript 文件的最大依赖深度。
5.Emit
5.1 declaration、declarationMap、emitDeclarationOnly、declarationDir
- "declaration": true:生成对应的 .d.ts 声明文件。
- "declarationMap": true:为 .d.ts 文件生成 source map 文件。
- "emitDeclarationOnly": true:仅仅生成 .d.ts 声明文件而不会生成对应的 JavaScript 代码文件。js的sourceMap也不会生成
- "declarationDir": "./":指定 .d.ts 声明文件的输出目录。通常与 "declaration": true 配合使用。
5.2 outFile、sourceMap、outDir、removeComments
- "sourceMap": true:为 JavaScript 代码生成对应的 source map 文件。
- "outFile": "./":将所有编译后的 JavaScript 代码合并为一个文件输出到指定目录中。如果同时配置 "declaration": true,则会将所有生成的 .d.ts 声明文件也合并到该文件中。 注:除非
module
是None
,System
或AMD
, 否则不能使用outFile
。 这个选项 不能 用来打包 CommonJS 或 ES6 模块。 - "outDir": "./dist":指定一个目录,将所有编译后的 JavaScript 代码和 .d.ts 声明文件输出到该目录下。
- "removeComments": true:禁止在编译后的 JavaScript 代码中保留注释。
案例:
outDir和outFile都配置,以outFile为准
outDir : './dist' 注意:如果设置了outFile,以outFile设置为准,因为可能设置成不同文件夹,如果需要为dist 则outFile设为 ‘./dist/index.js’
removeComments: 删除编译后的注释
sourceMap代码映射 方便调试
{"version":3,"file":"index.js","sourceRoot":"","sources":\["index.ts"],"names":\[],"mappings":";;AAAA,uCAAkC;AAClC,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,gBAAK,CAAC,CAAA"}
5.3 noEmit、noEmitError
- "noEmit": true:禁止编译器输出任何文件,通常与其他配置项配合使用(如结合项目构建工具)。
- "noEmitOnError": true:当存在编译错误时,禁止输出任何文件。
5.4 importHelpers、noEmitHelpers、downlevelIteration
-
"importHelpers": true:对于某些降级行为,TypeScript 使用一些辅助代码来进行操作。例如继承类,展开数组或对象,以及异步操作。 默认情况下,这些辅助代码被插入到使用它们的文件中。 如果在许多不同的模块中使用相同的辅助代码,则可能会导致代码重复。
如果启用了
importHelpers
选项,这些辅助函数将从 tslib 中被导入。 你需要确保tslib
模块在运行时可以被导入。 这只影响模块,全局脚本文件不会尝试导入模块。 -
"downlevelIteration": true:‘降级’ 是 TypeScript 的术语,指用于转换到旧版本的 JavaScript。如for...of会变成for循环。注: 如果在运行时不存在
Symbol.iterator
,启用downlevelIteration
将不会提高合规性。 -
"noEmitHelpers": true:当你提供了自行实现的这些函数时,不需要tsli导入的辅助函数
5.5 inlineSourceMap、inlineSources
-
"inlineSourceMap": true:将 sourcemap 文件嵌入到生成的 JavaScript 代码中。
-
"inlineSources": true:将源代码嵌入到 sourcemap 文件中。
会在文件内生成一段注释,包含文件的源映射
5.6 importsNotUsedAsValues、preserveValueImports(已弃用)
-
"importsNotUsedAsValues": "remove":定义 import 语句的行为,如果仅仅在类型声明中使用,则直接移除该语句。
-
"preserveValueImports": true:保留未使用的 imported value 在 JavaScript 输出中的定义,不会被删除。
使用verbatimModuleSyntax
5.7 其他
-
"sourceRoot": "":为调试器指定查找引用源代码的根路径。
-
"mapRoot": "":为调试器指定查找 map 文件的位置。
-
"emitBOM": true:在输出文件开头添加 UTF-8 BOM 字符。
-
"newLine": "crlf":设置输出文件的换行符类型(Windows 中常用 crlf,Linux/MacOS 中常用 lf)。
-
"stripInternal": true:禁止生成注释中包含 "@internal" 的声明。在其 JSDoc 注释中具有
@internal
注释的代码 -
"preserveConstEnums": true:保留被声明为 const enum 的枚举类型定义。
6.Interop Constraints
- "isolatedModules": true:确保每个文件都可以安全地转换为 JavaScript 代码,而不需要依赖其他导入。这可以确保所有变量和函数都已定义并可访问,因此可以减少编译时出现错误的可能性。
- "allowSyntheticDefaultImports": true:允许在没有默认导出的模块中使用 "import x from y" 导入方式。在这种情况下,TypeScript 将生成一个命名导入以符合 ES6 的规范。
- "esModuleInterop": true:为了兼容 CommonJS 和 ES6 模块,在导入 CommonJS 模块时生成一些额外的 JavaScript 代码。同时,该选项也会启用 "allowSyntheticDefaultImports" 以便提高类型兼容性。
- "forceConsistentCasingInFileNames": true:确保导入时的大小写写法正确。如果文件系统不区分大小写,则 TypeScript 会根据文件名的首字母大小写来匹配导入名称。这有助于避免常见的大小写错误。
7.Type Checking
-
"strict": true:启用所有严格的类型检查选项,包括 "noImplicitAny"、"strictNullChecks"、"strictFunctionTypes"、"strictBindCallApply"、"strictPropertyInitialization"、"noImplicitThis" 等选项。该选项可以帮助开发者更早地发现代码中的潜在错误。
-
"noImplicitAny": true:对隐式推断出的 "any" 类型进行报错提示。如果开启了该选项,则 TypeScript 会报出所有未显式指定类型或无法从上下文中推断出类型的变量和函数参数/返回值的警告。
-
"strictNullChecks": true:在类型检查时将 "null" 和 "undefined" 算作不同类型,避免异常情况。如果开启了该选项,则编译器会强制处理这些情况,以便在运行时避免绝大多数的 null 或 undefined 错误。
-
"strictFunctionTypes": true:在赋值函数类型时检查参数和返回值类型是否兼容。这有助于在开发过程中及时发现类型错误,同时也可以确保代码的安全性。
-
"strictBindCallApply": true:检查 "bind"、"call" 和 "apply" 方法调用的参数是否与原函数匹配。这可以确保代码的正确性和稳定性。
-
"strictPropertyInitialization": true:检查类属性是否在构造函数中初始化。这有助于避免在使用未初始化的属性时出现错误。
-
"noImplicitThis": true:启用当 'this' 被赋予 'any' 类型时的错误报告。在 TypeScript 中,如果没有正确地指定上下文类型,则 'this' 变量会被推断为 'any' 类型,从而可能导致潜在的错误。
-
"useUnknownInCatchVariables": true:在 catch 语句中将变量默认为 unknown 类型而非 any 类型,以提高类型安全性。
-
"alwaysStrict": true:始终生成包含 'use strict' 的 JavaScript 代码文件,以确保代码的严谨性和正确性。
-
"noUnusedLocals": true:启用当局部变量未使用时的错误报告。在开发过程中,如果存在未使用的局部变量,则很可能是一种代码质量问题。
-
"noUnusedParameters": true:启用当函数参数未使用时的错误报告。在开发过程中,如果存在未使用的函数参数,则很可能是一种代码质量问题。
-
"exactOptionalPropertyTypes": true:以编写的形式解析可选属性类型,而不是添加 "undefined"。保证代码的准确性和可读性。
-
"noImplicitReturns": true:启用当函数缺少显式返回值时的错误报告。在开发过程中,这有助于及时发现未完整编写的代码分支。
-
"noFallthroughCasesInSwitch": true:启用在 switch 语句中检测落空分支的错误报告,以提高代码的准确性和可读性。
-
"noUncheckedIndexedAccess": true:在使用索引访问数组元素时增加对 undefined 类型的处理,以提高代码的健壮性。
-
"noImplicitOverride": true:确保派生类中的重载成员被标记为 override。这有助于避免基本类的成员函数和变量被无意地覆盖。
-
"noPropertyAccessFromIndexSignature": true:强制使用索引访问器来访问声明为索引类型的键。保证代码的可读性和正确性。
-
"allowUnusedLabels": true:禁用未使用标签的错误报告。在某些情况下,可能需要使用未使用的标签。
-
"allowUnreachableCode": true:禁用无法到达的代码的错误报告。在某些情况下,可能会存在不可到达的代码分支,但这不一定是代码质量问题。
7.1 strict alwaysStrict
会默认将结果加上 'use strict'
alwaysStrict 会每次加上
use strict
是 JavaScript 中的一种严格模式,它在 ECMAScript 5(简称 ES5)中被引入。通过在脚本或函数的顶部添加 use strict
声明,可以启用严格模式。严格模式会对代码执行施加一些限制,以此来避免某些常见的错误和不安全的行为。这些限制包括:
- 全局变量必须显式声明:在严格模式下,如果不使用
var
、let
或const
关键字来声明变量,将会抛出错误。
"use strict";
x = 10; // 抛出 ReferenceError: x is not defined
- 禁止删除已声明的变量:在非严格模式下,可以使用
delete
操作符删除已声明的变量。但在严格模式中,这将导致语法错误。
"use strict";
var x = 10;
delete x; // 抛出 SyntaxError
- 禁止重复的参数名称:在严格模式下,函数参数中不允许有重复的参数名称。
"use strict";
function myFunc(a, a) {} // 抛出 SyntaxError: Duplicate parameter name not allowed in this context
- 禁止八进制数字语法:在严格模式下,不允许使用八进制字面量(以 0 开头的数字)。
"use strict";
var x = 0123; // 抛出 SyntaxError: Octal literals are not allowed in strict mode
- 对
this
的限制:在非严格模式下,全局作用域中的this
指向全局对象(浏览器环境中是window
)。在严格模式下,全局作用域中的this
值为undefined
。
"use strict";
console.log(this); // 输出 undefined
-
禁止使用
with
语句:在严格模式下,不允许使用with
语句,该语句会导致代码难以理解和调试。 -
显示错误:严格模式更容易发现潜在的错误。例如,在赋值给只读属性时,非严格模式下可能会默默失败,而严格模式下将抛出错误。
7.2. noImplicitThis
this不确定报错 默认是false
;()=> {
console.log('打印***a', this)
}
设置为true,vscode报错
设置为false正常
7.3. noUnusedLocals
"noUnusedLocals": true, /* 用于检查是否有定义了但是没有使用的变量,对于这一点的检测,使用eslint可以在你书写代码的时候做提示,你可以配合使用。它的默认值为false */
7.4 noImplicitAny
为隐含的any报错,设置为true, x没有定义会报错
8.Completeness
8.1 skipDefaultLibCheck、skipLibCheck
skipDefaultLibCheck(不用),推荐使用skipLibCheck代替
以.d.ts声明的为库文件,不能进行赋值,设置为true可以直接跳过检查
转载自:https://juejin.cn/post/7240765897768878139