[Typescript]配置文件之 tsconfig.json

[Typescript]配置文件之 tsconfig.json

  • 什么是 tsconfig.json
  • 编译
    • 编译文件
    • 编译整个项目
    • tsconfig.json 文件
      • tsconfig.json 文件生成
      • tsconfig.json 初始化文件
      • tsconfig.json 常用配置
      • tsconfig.json 顶级配置选项
        • files
        • extends
        • include/exclude
        • references
        • compilerOptions
        • compilerOptions 编译选项配置详解
          • 类型检查类配置
            • exactOptionalPropertyTypes
            • noImplicitReturns
            • noPropertyAccessFromIndexSignature
            • noUncheckedIndexedAccess
            • strictFunctionTypes
            • strictNullChecks
            • strictPropertyInitialization
            • useUnknownInCatchVariables
            • 模块化配置选项
              • allowUmdGlobalAccess
              • baseUrl
              • module
              • moduleResolution
              • resolveJsonModule
              • typeRoots
              • types
              • 文件生成配置
                • declaration
                • emitBOM
                • importHelpers
                • importsNotUsedAsValues
                • inlineSourceMap
                • outDir
                • JavaScript 支持配置
                • Editor 支持配置
                • 操作约束设置
                  • allowSyntheticDefaultImports
                  • esModuleInterop
                  • forceConsistentCasingInFileNames
                  • isolatedModules
                  • 向后兼容性设置
                    • noImplicitUseStrict
                    • noStrictGenericChecks
                    • suppressExcessPropertyErrors
                    • suppressImplicitAnyIndexErrors
                    • 语言和环境设置
                      • emitDecoratorMetadata
                      • experimentalDecorators
                      • jsx
                      • jsxFactory
                      • jsxFragmentFactory
                      • jsxImportSource
                      • moduleDetection
                        • noLib
                        • reactNamespace
                        • target
                        • lib
                        • 编译和策略设置
                        • 项目设置
                        • 输出格式设置
                        • 完整性设置
                        • watchOptions 观察选项配置详解
                          • watchFile
                          • watchDirectory
                          • fallbackPolling
                          • Type Acquisition 选项配置详解

                            什么是 tsconfig.json

                            项目根目录包含 tsconfig.json 文件,表明该项目为 typescript 项目。

                            该文件一般位于根目录,并设定编译选项

                            JavaScript 项目类似功能文件是在根目录中设置 jsconfig.json 文件

                            编译

                            编译文件

                            我们知道 tsc 命令可以将一个 ts 文件编译为 js 文件

                            tsc [name].ts;
                            

                            编译整个项目

                            那么当我们开发一个项目的时候都是使用的 ts 开发的,难道需要手动用 tsc 去编译每个文件么?

                            不需要的。

                            只要在项目中初始化 tsconfig.json 文件,定义 tsc 的编译配置,此时执行 tsc 命令,会根据 tsconfig.json 配置文件自动

                            编译整个项目

                            tsconfig.json 文件

                            tsconfig.json 文件生成

                            tsc --init
                            

                            tsconfig.json 初始化文件

                            执行以上命令生成 tsconfig.json 默认初始化文件

                            { "compilerOptions": { /* 官网文档配置 https://aka.ms/tsconfig */
                                /* Projects */
                                "incremental": true,  /* 保存 .tsbuildinfo 文件,增量编译 提高编译速度*/
                                "composite": true, /* 用于约束是否允许项目引用 */
                                "tsBuildInfoFile": "./.tsbuildinfo", /* 指定增量编译文件 .tsbuildinfo 存储路径 */
                                // "disableSourceOfProjectReferenceRedirect": true,  /* 复合文件中使用声明文件而不是源文件 */
                                "disableSolutionSearching": true,/* 复合项目中,跳转到引用的定义位置*/
                                "disableReferencedProjectLoad": true,/*使用该标志来禁用引用项目的自动加载,在复合项目比较大的时候比较有用 */
                                /* Language and Environment */
                                "target": "es2016", /* 设置编译输出目标*/
                                "lib": [],/* 编译过程或运行时需要引入的库文件的列表*/
                                // "jsx": "preserve",      /* jsx代码转换输出 */
                                // "experimentalDecorators": true,   /* 实验性支持TC39 第二阶段decorators草案 */
                                // "emitDecoratorMetadata": true,    /* 为源文件中的装饰器声明提交元数据设计类型 */
                                // "jsxFactory": "",       /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
                                // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
                                // "jsxImportSource": "",  /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
                                // "reactNamespace": "",   /* 指定调用'createElement'的对象.提交'react' JSX时应用 */
                                // "noLib": true,/* 禁用库文件,包括lib.d.ts */
                                // "useDefineForClassFields": true,  /* Emit ECMAScript-standard-compliant class fields. */
                                // "moduleDetection": "auto",/* Control what method is used to detect module-format JS files. */
                                /* Modules */
                                "module": "commonjs", /* 项目采用的模块化开发规范*/
                                "rootDir": "./", /* 设置文件的根目录,改变编译后文件的输出目录*/
                                "moduleResolution": "node", /* 指定模块的解析策略 */
                                "baseUrl": "./", /* 设置项目的基本路径*/
                                "paths": {}, /* 重新映射包的相对路径 */
                                "rootDirs": [],  /* 当解析模块时,根目录下的多文件夹,可视作一个文件夹*/
                                "typeRoots": [], /* 设置声明文件的根目录*/
                                "types": [], /* 被引入项目的包的类型*/
                                "allowUmdGlobalAccess": true, /* 允许全局引入UMD模块 */
                                "moduleSuffixes": [],/* 解析文件名时使用的后缀 */
                                "resolveJsonModule": true,/* 允许引入.json文件 */
                                "noResolve": true,/* 不允许 import,require,reference 引用的文件被加载到项目中 */
                                /* JavaScript Support */
                                "allowJs": true,/*允许引入js文件*/
                                "checkJs": true,/* 会显示js文件错误提示*/
                                "maxNodeModuleJsDepth": 1,/* 在node_modules搜索文件夹与加载js文件的最大深度 */
                                /* Emit */
                                "declaration": true,/* 项目中的js或ts文件生成对应的js文件和 .d.ts 文件*/
                                "declarationMap": true,/* 产生 .d.ts文件对应的map文件*/
                                "emitDeclarationOnly": true,/*仅输出d.ts files并不生成js文件*/
                                "sourceMap": true,/* 创建生成js文件对应的map文件 */
                                "outFile": "./",/* 所有内容的输出文件.declaration为true时所有声明文件也都输出到一个 .d.ts 文件 */
                                "outDir": "./", /* 所有生成文件的输出目录*/
                                "removeComments": true,/* 输出文件中删除评论 */
                                "noEmit": true, /* 禁止Typescript编译器输出文件,使用三方规则 */
                                "importHelpers": true,/* 帮助全局引入一些兼容代码,而不是在每个文件中引入*/
                                "importsNotUsedAsValues": "remove",/* 说明imports的使用法师 */
                                "downlevelIteration": true, /* 代码降级,允许更多兼容性代码,使得新的代码能够在老的运行环境中运行 */
                                "sourceRoot": "",/* 说明调试的源代码的位置*/
                                "mapRoot": "",  /* 说明调试器使用的map文件位置,并不是map的生成位置*/
                                "inlineSourceMap": true,/* 将map文件的内容内嵌到生成的js文件中 */
                                "inlineSources": true,  /* 将源文件的内容也内嵌到map文件中,因此map文件与不内嵌源文件的内容是不同的*/
                                "emitBOM": true,/* 在输出文件的顶端生成UTF-8编码的字节顺序标记*/
                                "newLine": "crlf",/* 设置换行符使用的字符,Dos系统crlf,unix系统lf*/
                                "stripInternal": true, /* 删除@internal标签的声明*/
                                "noEmitHelpers": true,  /* 禁用自动生成的兼容内容,可以自定义全局兼容内容 */
                                "noEmitOnError": true,/*报错情况下禁止生成文件*/
                                "preserveConstEnums": true,/* 保留 const enum 声明*/
                                "declarationDir": "./",/* 生成的声明文件的输出目录*/
                                "preserveValueImports": true,/* 输出文件中是否保留未使用的引入 */
                                /* Interop Constraints */
                                "isolatedModules": true,/* 该选项设置所有文件可以被安全引入*/
                                "allowSyntheticDefaultImports": true,     /* 允许直接 'import x from y' 当没有默认导出时*/
                                "esModuleInterop": true,   /* 输出额外代码支持更简易的方式导入 CommonJS 模块. */
                                "preserveSymlinks": true, /* 解析符号链接所在文件的相对位置,而不是符号链接的位置*/
                                "forceConsistentCasingInFileNames": true,    /* 确保引入文件的正确性,文件名大小写敏感 */
                                /* Type Checking */
                                "strict": true, /* 允许strict类型检查 */
                                "noImplicitAny": true,/*是否可以设置any类型*/
                                "strictNullChecks": true, /*检查 null与undefined 的使用 */
                                "strictFunctionTypes": true,/* 函数赋值时确保参数类型与变量的类型的一致性*/
                                "strictBindCallApply": true, /* 检查函数使用bind, call, apply方法参数是否正确 */
                                "strictPropertyInitialization": true, /* 是否检查类的属性是否赋值*/
                                "noImplicitThis": true, /* 检查是否通过使用this隐式赋予'any'类型 */
                                "useUnknownInCatchVariables": true, /* 默认any类型的catch分支参数error是否需要设置为unknown */
                                "alwaysStrict": true, /* 文件最上添加 'use strict' 模式*/
                                "noUnusedLocals": true, /*未使用的局部变量报错*/
                                "noUnusedParameters": true, /* 未使用的参数报错 */
                                "exactOptionalPropertyTypes": true, /* 严格检查具有后缀?的接口或属性取值 */
                                "noImplicitReturns": true, /* 是否检查函数返回情况*/
                                "noFallthroughCasesInSwitch": true, /* 检查switch表达式的正确性,每个非空case都有break,或者return */
                                "noUncheckedIndexedAccess": true, /* 为未定义 默认string的obj.attr 添加 'undefined' 类型*/
                                "noImplicitOverride": true, /* 检查派生类重写的方法是否使用override 修饰符*/
                                "noPropertyAccessFromIndexSignature": true, /* 检查属性是否存在 */
                                "allowUnusedLabels": true, /*代码中的无效标签提示 */
                                "allowUnreachableCode": true, /*代码中的无效代码提示 */
                                /* Completeness */
                                "skipDefaultLibCheck": true, /* 可用 skipLibCheck替代*/
                                "skipLibCheck": true /* 是否跳过声明文件.d.ts 的类型检查 . */
                              }
                            }
                            

                            tsconfig.json 常用配置

                            { // 编译选项
                              "compilerOptions": { "outDir": "./output",// 编译生成文件的输出目录
                                "sourceMap": true, // 是否包含可以用于 debug 的 sourceMap
                                // 以严格模式解析
                                "strict": true,
                                "module": "esnext",
                                "moduleResolution": "node",
                                "target": "es5",
                                // 允许从没有设置默认导出的模块中默认导入
                                "allowSyntheticDefaultImports": true,
                                // 将每个文件作为单独的模块
                                "isolatedModules": false,
                                // 启用装饰器
                                "experimentalDecorators": true,
                                // 启用设计类型元数据(用于反射)
                                "emitDecoratorMetadata": true,
                                // 在表达式和声明上有隐含的any类型时报错
                                "noImplicitAny": false,
                                "noImplicitReturns": true,
                                "importHelpers": true,// 从 tslib 导入外部帮助库: 比如__extends,__rest等
                                "listFiles": true,// 编译过程中打印文件名
                                "removeComments": true,// 移除注释
                                "suppressImplicitAnyIndexErrors": true,
                                // 允许编译javascript文件
                                "allowJs": true,
                                // 解析非相对模块名的基准目录
                                "baseUrl": "./",
                                "paths": { "jquery": [
                                    "node_modules/jquery/dist/jquery"
                                  ]
                                },
                                "lib": [
                                  "dom",
                                  "es2015",
                                  "es2015.promise"
                                ]
                              }
                            }
                            

                            tsconfig.json 顶级配置选项

                            是对于 tsconfig.json 文件中的选项进行介绍,也即最外层的配置选项

                            顶级属性描述
                            compilerOptions编译器的配置选项
                            files程序包含的文件,若列表文件没找到会报错
                            include包含指定模式的系列文件
                            exclude排除系列文件,如 node_modules
                            references构造更小项目碎片,改善打包/编辑的迭代时间
                            extends引入其它 tsconfig.json 文件

                            files

                            当程序包含的文件不多的时候使用 files 指定被编译文件的列表,若列表文件没找到会报错;只有需要编译的文件少时才会用到 files,如果需要编译的文件较多时使用 include

                            extends

                            如果 tsconfig.json 文件引入其它配置文件,例如 base.json,可以继承 base.json 中的配置选项。如果有相同的配置项,tsconfig.json 采用就近原则,覆盖 base.json 中的配置项。不允许循环继承

                            include/exclude

                            include 与 exclude 可以使用通配符,指定一系列被编译或排除编译的文件

                            • - 表示任意字符(不包括目录目录分隔符)
                            • ?表示某个字符是否包含(不包括目录目录分隔符)
                            • **/ 匹配任意目录,任意级别

                              references

                              1. 可以设置指定标志的代指路径,用于方便代码编写
                              "references": [{ "@": "../src" }]
                              
                              1. 可以在复合项目中引入其它项目
                              • 被引入的是项目的模块,而不是它导出的声明文件(.d.ts)
                              • 如果被引入的是项目有导出的声明文件,那么这些声明文件对复合项目是可见的
                              • 如果有需要,打包模式会自动打包被引入的项目

                                使用项目隔离的方式,可以改善类型检查或编译(代码变更)的效率

                                compilerOptions

                                编译选项是配置文件中非常重要也比较复杂的配置选项,在 compilerOptions 中包含多个子选项,用来完成对编译的配置,因为 compilerOptions 选项较多,所以单独抽取一个章节详细介绍


                                compilerOptions 编译选项配置详解

                                compilerOptions 中的配置项可以根据作用进行分类,下面根据作用分别简介其中的配置项

                                类型检查类配置

                                属性描述
                                Type Checking 项目根据设置不符合要求会在错误报告中显示
                                allowUnreachableCode代码中无效代码提示,undefined 警告,true 忽略,false 报错
                                allowUnusedLabels代码中无效标签提示,取值同上
                                alwaysStrict文件被严格模式解析,也就是每个文件最上添加 ‘use strict’
                                exactOptionalPropertyTypes是否需要检查项目中后缀添加?的属性的取值
                                noFallthroughCasesInSwitch检查 switch 表达式的正确性,每个非空 case 都有 break,或者 return
                                noImplicitAny是否可以设置 any 类型
                                noImplicitOverride检查派生类重写的方法是否需要使用 override 修饰符,true 不需要要,false,必须有有修饰符,否则报错
                                noImplicitReturns是否检查函数返回情况
                                noImplicitThis是否检查通过使用 this 隐式赋予’any’类型
                                noPropertyAccessFromIndexSignature是否检查代码中使用了 obj.attr 语法获取未明确声明 attr 的值
                                noUncheckedIndexedAccess为未定义 默认 string 的 obj.attr 添加 ‘undefined’ 类型
                                noUnusedLocals未使用的局部变量报错
                                noUnusedParameters未使用的参数报错
                                strict严格模式
                                strictBindCallApply检查函数使用 bind, call, apply 方法参数是否正确
                                strictFunctionTypes函数赋值时确保参数类型与变量的类型的一致性
                                strictNullChecks检查 null 与 undefined 的情况
                                strictPropertyInitialization是否检查类的属性是否赋值
                                useUnknownInCatchVariables默认 any 类型的 catch 分支参数 error 是否需要设置为 unknown

                                exactOptionalPropertyTypes

                                是否需要检查项目中后缀添加?的属性的取值,也即严格检查可选属性的类型

                                例如,

                                interface UserDefaults { colorThemeOverride?: "dark" | "light";
                                }
                                

                                如果设置 exactOptionalPropertyTypes:true,需要列出属性的可选值,

                                const settings = getUserDetail();
                                

                                settings.colorThemeOverride 取值可以为"dark" 或 “light”,但是不能设置为"undefined",可以 settings 没有 colorThemeOverride 属性,以下两者不等价

                                settings = { //可以
                                  name: "",
                                  age: ""
                                };
                                settings = { //不可
                                  name: "",
                                  age: "",
                                  colorThemeOverride: undefined
                                };
                                

                                noImplicitReturns

                                是否检查函数返回情况

                                若设置为 true,需要根据函数设置的返回类型检查函数的返回值,需要检查函数是否每个分支都有返回值,void 函数除外

                                noPropertyAccessFromIndexSignature

                                是否检查 obj.attr

                                若设置为 true ,需要检查是否使用 object.attr 语法获取没有明确定义的属性。如果 attr 没有定义,使用该方式将会报错,可以通过 object[attr]方式获取该值;

                                若设置为 false ,则无需检查;

                                noUncheckedIndexedAccess

                                声明了 obj 类型,若是 obj.attr 是没有明确定义的属性

                                noUncheckedIndexedAccess 设置为 false ,则 attr 使用索引标记的方式设置为 string 类型;

                                noUncheckedIndexedAccess 设置为 true ,则 attr 使用索引标记的方式设置为 string|undefined 类型

                                为未定义的默认 string 的 obj.attr 添加 ‘undefined’ 类型

                                strictFunctionTypes

                                函数赋值时确保参数类型与变量的类型的一致性

                                function fn(x: string) { console.log("Hello, " + x.toLowerCase());
                                }
                                type StringOrNumberFunc = (ns: string | number) => void;
                                // Unsafe assignment is prevented
                                let func: StringOrNumberFunc = fn;
                                

                                strictNullChecks

                                检查 Null 与 undefined 的情况

                                • 仅声明未赋值
                                • 未定义,未声明

                                  strictPropertyInitialization

                                  是否检查类的属性是否赋值

                                  当设置为 true 时,需要检查类的属性是否仅仅只是声明,没有赋值。

                                  类 Class 中属性赋值的场景:

                                  • 类中声明,并在构造函数中赋值
                                  • 在声明同时设置默认值
                                  • 声明的类型中包括 undefined 可以不赋值

                                    其它情况,默认为没有赋值情况,会有错误提示

                                    当设置为 false 时,不检查

                                    useUnknownInCatchVariables

                                    在 strict 模式下,是否需要设置 catch 语句中捕捉的 error 类型为 unknow,error 默认是 any 类型

                                    当设置为 false 时,需要设置 error 类型:unknow,否则报错

                                    try { // ...
                                    } catch (err: unknow) { if (err instanceof Error) { console.log(err.message);
                                      }
                                    }
                                    

                                    当设置为 true 时,不需要设置 error 类型

                                    try { // ...
                                    } catch (err) { if (err instanceof Error) { console.log(err.message);
                                      }
                                    }
                                    

                                    模块化配置选项

                                    属性描述
                                    Modules 模块化设置
                                    allowUmdGlobalAccess允许全局引入 UMD 模块
                                    baseUrl设置项目的基本路径
                                    module项目使用的模块规范
                                    moduleResolution指定模块的解析策略
                                    moduleSuffixes解析 import 等文件名时使用的后缀
                                    noResolve不允许 import,require,reference 引用的文件被加载到项目中
                                    paths重新映射包的相对路径
                                    resolveJsonModule解析引入.json 的静态文件
                                    rootDir设置文件的根目录,改变编译后文件的输出目录
                                    rootDirs解析模块时,根目录下的多文件夹,可视作一个文件夹
                                    typeRoots设置声明文件的根目录
                                    types设置 node_modules/@types 目录下会被项目加载的包的类型名

                                    allowUmdGlobalAccess

                                    若为 true,则允许全局引入 UMD 模块

                                    否则,需要每次 import 模块才可以使用

                                    baseUrl

                                    设置项目的基本路径,用于解析项目中的路径;

                                    module

                                    项目使用的模块化开发规范

                                    moduleResolution

                                    指定模块的解析策略,也即如何处理模块

                                    当 module 设置为 AMD, UMD, System or ES6/ES2015,moduleResolution 设置为 classic;

                                    当 module 设置为 Commonjs,moduleResolution 设置为 node;

                                    其它情况,moduleResolution 设置为 nodenext,node12;

                                    resolveJsonModule

                                    resolveJsonModule 设置为 true,允许引入.json 文件;

                                    node 正常情况下是允许引入.json 静态文件的

                                    但是 typescript 默认不支持引入.json 静态文件,所以需要设置该选项

                                    typeRoots

                                    设置类型声明文件的根目录,默认情况下,包对应的类型文件是在 node_modules/@types 目录下,因此默认值是包含 node_modules/@types 的路径。

                                    但是修改后则仅仅是修改后的路径下的类型文件,所有解析类型都会到 typeRoots 设置的目录列表中查询

                                    types

                                    设置可以使用的类型文件,例如默认情况下所有使用的包都到对应的 node_modules/@types 下查找对应的类型

                                    但是一旦设定 types ,那么只有 types 指定列表中的包可以到 node_modules/@types 下查找对应的类型,其它的例如不在 types 设置的列表中,但是在 node_modules/@types 下的类型包,将不会被引入项目

                                    文件生成配置

                                    属性描述
                                    Emit 生成文件配置
                                    declarationjs/ts 文件生成对应的 js 文件和 d.ts 文件
                                    declarationDir生成的声明文件的输出目录
                                    declarationMap创建 d.ts 文件对应的 map 文件
                                    emitDeclarationOnly仅输出 d.ts 文件并且不生成 js 文件
                                    downlevelIteration允许程序在老环境中运行,生成兼容的降级代码
                                    emitBOM在输出文件顶端是否生成字节顺序编码
                                    importHelpers全局引入兼容代码,而不是在每个文件中引入
                                    importsNotUsedAsValues决定 imports 的使用方式
                                    inlineSourceMap将 map 文件的内容内嵌到生成的 js 文件中
                                    inlineSources将源文件的内容内嵌到 map 文件中
                                    mapRoot说明调试器使用的 map 文件位置
                                    newLine设置换行字符,Dos 系统 crlf,unix 系统 lf
                                    noEmit不许默认编辑器生成 map 等文件,通过三方工具
                                    noEmitHelpers禁用自动生成的兼容内容,可以自定义全局兼容内容
                                    noEmitOnError报错时禁止编译生成文件
                                    outDir所有生成文件的输出目录
                                    outFile编译的输出文件,module 为 none/system/amd 时才可用
                                    preserveConstEnums保留 const enum 声明
                                    preserveValueImports输出文件中是否保留未使用的引入
                                    removeComments输出文件中删除评论
                                    sourceMap创建生成 js 文件对应的 map 文件
                                    sourceRoot说明调试的源代码的位置
                                    stripInternal删除@internal 标签的声明

                                    declaration

                                    项目中的 js 或 ts 文件编译成对应的 js 文件和 d.ts 声明文件

                                    ts 文件如此没有任何问题,因为生成 js 文件的后缀名不同;但是 js 文件生成声明文件同时生成 js 文件就会存在问题,导致生成的 js 文件可能会覆盖原有的 js 文件,因此对于 js 项目,设置 emitDeclarationOnly,仅生成声明文件,防止覆盖问题

                                    例如,.ts 文件

                                    export let helloWorld = "hi";
                                    

                                    生成 js 文件

                                    export let helloWorld = "hi";
                                    

                                    生成 d.ts 文件

                                    export declare let helloWorld: string;
                                    

                                    emitBOM

                                    在编译的输出文件顶端插入 UTF-8 编码的字节序列标记,因为存在部分运行环境需要该序列标记说明 javascript 文件;该值取值默认是 false,如果没有特别的需要,最好不要改变该值

                                    importHelpers

                                    帮助全局引入一些兼容代码,而不是在每个文件中引入,例如从 tslib 导入外部帮助库**extends,**rest 等

                                    export function fn(arr: number[]) { const arr2 = [1, ...arr];
                                    }
                                    

                                    该代码使用了 ES6 的语法,可能在一些老的运行环境无法识别该代码,因此需要设置 downlevelIteration 为 true,允许编译时添加一些兼容性的代码

                                    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 __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));
                                      };
                                    export function fn(arr) { var arr2 = __spreadArray([1], __read(arr), false);
                                    }
                                    

                                    此时如果没有设置 importHelpers 为 true,那么每个使用该 ES6 的语法处都会插入上述兼容性代码,导致很多重复性代码

                                    如果设置 importHelpers 为 true

                                    import { __read, __spreadArray } from "tslib";
                                    export function fn(arr) { var arr2 = __spreadArray([1], __read(arr), false);
                                    }
                                    

                                    如果你是自己编写该语法的兼容代码,可以设置 noEmitHelpers

                                    importsNotUsedAsValues

                                    主要是决定 import 的使用方式

                                    • remove:默认取值,表示之引入 import 的包的类型
                                    • preserve : 引入整个包,不论是否使用,包括包与包的类型声明
                                    • error : 引入整个包,包括包与包的类型声明,但是如果只是使用了包的声明文件会报错

                                      inlineSourceMap

                                      就是允许生成 map 文件的前提下,map 文件的内容是内嵌到 js 文件中的

                                      例如:

                                      "use strict";
                                      const helloWorld = "hi";
                                      console.log(helloWorld);
                                      //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDO0FBQ3hCLE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMifQ==
                                      

                                      outDir

                                      outDir 用来指定编译后文件所在的目录

                                      默认情况下,编译后的 js 文件会和 ts 文件位于相同的目录,设置 outDir 后可以改变编译后文件的位置

                                      JavaScript 支持配置

                                      属性描述
                                      JavaScript Support 选项
                                      allowJs允许引入 js 文件
                                      checkJs会显示 js 文件错误提示
                                      maxNodeModuleJsDepth在 node_modules 搜索文件夹与加载 js 的最大深度

                                      Editor 支持配置

                                      属性描述
                                      Editor 支持选项
                                      disableSizeLimit禁用项目分配的内存限制
                                      plugins编辑器使用的语言服务插件

                                      操作约束设置

                                      属性描述
                                      allowSyntheticDefaultImports允许直接 import 非默认的导出
                                      esModuleInterop输出额外代码支持更简易方式导入 CommonJS 模块
                                      forceConsistentCasingInFileNames引入文件文件名大小写敏感
                                      isolatedModules该选项设置所有文件可以被安全引入
                                      preserveSymlinks解析符号链接所在文件相对位置,不是符号链接的位置

                                      allowSyntheticDefaultImports

                                      当一个模块没有默认导出时,我们一般使用

                                      import * as React from "react";
                                      

                                      但是当设置 allowSyntheticDefaultImports 为 true 时,可以使用以下方式

                                      import React from "react";
                                      

                                      如果该选项没有设置为 true 时,使用该方式导入没有默认导出的模块会报错

                                      esModuleInterop

                                      启用 esModuleInterop,也将会启用 allowSyntheticDefaultImports . esModuleInterop 默认值为 false;

                                      esModuleInterop 设置为 true 时,将使用两个 helper 函数改变 import 模块时的转译规则,使得 es 模块可以使用 ES6 的简易方式加载 Commonjs 规范的模块

                                      forceConsistentCasingInFileNames

                                      TypeScript 是大小写敏感的语言,介于引入文件的可能存在大小写敏感不确定,通过该选项可以设置

                                      isolatedModules

                                      该选项设置所有文件可以安全引入,因为要求每个文件都是单独的模块

                                      向后兼容性设置

                                      属性描述
                                      charset设置编码,已废弃
                                      keyofStringsOnly设置索引返回类型为 string ,已废弃
                                      noImplicitUseStrict禁用"use strict"模式
                                      noStrictGenericChecks禁用泛型检查
                                      out向后兼容的输出文件,已废弃
                                      suppressExcessPropertyErrors禁止额外的属性报错,已废弃
                                      suppressImplicitAnyIndexErrors禁止隐式 any 的报错

                                      noImplicitUseStrict

                                      我们一般不使用该属性.默认情况下,我们提交模块文件到非 ES6 的环境,需要使用 UseStrict 模式,使用该属性禁止"use strict" 模式

                                      noStrictGenericChecks

                                      在比较两个泛型函数时,TypeScript 将协调类型参数,该参数将会禁止检查

                                      type A = (x: T, y: U) => [T, U];
                                      type B = (x: S, y: S) => [S, S];
                                      function f(a: A, b: B) { b = a; // Ok
                                        a = b; // Error 检查的情况
                                        `Type 'B' is not assignable to type 'A'.
                                      Types of parameters 'y' and 'y' are incompatible.
                                      Type 'U' is not assignable to type 'T'.
                                      'T' could be instantiated with an arbitrary type which could be unrelated to 'U'.`;
                                      }
                                      

                                      suppressExcessPropertyErrors

                                      禁止额外的属性报错,例如:

                                      type Point = { x: number; y: number };
                                      const p: Point = { x: 1, y: 3, m: 10 };
                                      `Type '{ x: number; y: number; m: number; }' is not assignable to type 'Point'.
                                      Object literal may only specify known properties, and 'm' does not exist in type 'Point'.`;
                                      

                                      已废弃

                                      suppressImplicitAnyIndexErrors

                                      打开 suppressImplicitAnyIndexErrors

                                      开关,禁止报告隐式 any 的错误,例如

                                      const obj = { x: 10 };
                                      console.log(obj["foo"]);
                                      `
                                      Element implicitly has an 'any' type because expression of type '"foo"' can't be used to index type '{ x: number; }'.
                                      Property 'foo' does not exist on type '{ x: number; }'.`;
                                      

                                      这种方式会全面禁止,推荐使用@ts-ignore的方式

                                      语言和环境设置

                                      属性描述
                                      emitDecoratorMetadata为装饰符提供元数据支持
                                      experimentalDecorators支持 TC39 版本之前装饰符
                                      jsx控制 jsx 构造函数 打包后的输出
                                      jsxFactory工厂
                                      jsxFragmentFactory工厂代码片段
                                      jsxImportSource引入工厂的模块声明
                                      lib
                                      moduleDetection模块检测
                                      noLib禁用自动引入的库文件
                                      reactNamespace声明对象
                                      target编译的目标
                                      useDefineForClassFields定义升级版本的 ClassFields

                                      emitDecoratorMetadata

                                      默认值为 true,为模块中的装饰符提供实验性的元数据支持

                                      示例:

                                      function LogMethod(target: any, propertyKey: string | symbol, descriptor: PropertyDescriptor) { console.log(target);
                                        console.log(propertyKey);
                                        console.log(descriptor);
                                      }
                                      class Demo { @LogMethod
                                        public foo(bar: number) { // do nothing
                                        }
                                      }
                                      const demo = new Demo();
                                      

                                      emitDecoratorMetadata 不为 true:

                                      "use strict";
                                      var __decorate =
                                        (this && this.__decorate) ||
                                        function (decorators, target, key, desc) { var c = arguments.length,
                                            r = c < 3 ? target : desc === null ? (desc = Object.getOwnPropertyDescriptor(target, key)) : desc,
                                            d;
                                          if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
                                          else for (var i = decorators.length - 1; i >= 0; i--) if ((d = decorators[i])) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
                                          return c > 3 && r && Object.defineProperty(target, key, r), r;
                                        };
                                      function LogMethod(target, propertyKey, descriptor) { console.log(target);
                                        console.log(propertyKey);
                                        console.log(descriptor);
                                      }
                                      class Demo { foo(bar) { // do nothing
                                        }
                                      }
                                      __decorate([LogMethod], Demo.prototype, "foo", null);
                                      const demo = new Demo();
                                      

                                      设置 emitDecoratorMetadata 为 true:

                                      "use strict";
                                      var __decorate =
                                        (this && this.__decorate) ||
                                        function (decorators, target, key, desc) { var c = arguments.length,
                                            r = c < 3 ? target : desc === null ? (desc = Object.getOwnPropertyDescriptor(target, key)) : desc,
                                            d;
                                          if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
                                          else for (var i = decorators.length - 1; i >= 0; i--) if ((d = decorators[i])) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
                                          return c > 3 && r && Object.defineProperty(target, key, r), r;
                                        };
                                      var __metadata =
                                        (this && this.__metadata) ||
                                        function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
                                        };
                                      function LogMethod(target, propertyKey, descriptor) { console.log(target);
                                        console.log(propertyKey);
                                        console.log(descriptor);
                                      }
                                      class Demo { foo(bar) { // do nothing
                                        }
                                      }
                                      __decorate([LogMethod, __metadata("design:type", Function), __metadata("design:paramtypes", [Number]), __metadata("design:returntype", void 0)], Demo.prototype, "foo", null);
                                      const demo = new Demo();
                                      

                                      experimentalDecorators

                                      TC39 之后可以使用 emitDecoratorMetadata 支持装饰符,但是之前使用 experimentalDecorators

                                      jsx

                                      控制 jsx 的构造函数在 js 中的输出,只影响 tsx 文件中 jsx 相关代码在编译后在 js 的输出

                                      • react: js 文件中的 JSX 转换成等效的 React.createElement 调用
                                      • react-jsx: 转换成_jsx 调用
                                      • react-jsxdev: 转换成_jsx 调用
                                      • preserve: 无需转换
                                      • react-native:无需转换

                                        示例:

                                        .tsx 文件

                                        export const HelloWorld = () => 

                                        Hello world

                                        ;

                                        jsx=“react”,输出代码:

                                        import React from "react";
                                        export const HelloWorld = () => React.createElement("h1", null, "Hello world");
                                        

                                        jsx=“react-jsx”,React 17 输出代码:

                                        import { jsx as _jsx } from "react/jsx-runtime";
                                        export const HelloWorld = () => _jsx("h1", { children: "Hello world" });
                                        

                                        jsx=“react-jsxdev”,React 17 输出代码:

                                        import { jsxDEV as _jsxDEV } from "react/jsx-dev-runtime";
                                        const _jsxFileName = "/home/runner/work/TypeScript-Website/TypeScript-Website/index.tsx";
                                        export const HelloWorld = () => _jsxDEV("h1", { children: "Hello world" }, void 0, false, { fileName: _jsxFileName, lineNumber: 9, columnNumber: 32 }, this);
                                        

                                        jsx=“preserve||react-native”,因为不需要转换,因此输出代码:

                                        export const HelloWorld = () => 

                                        Hello world

                                        ;

                                        jsxFactory

                                        编译 jsx 元素时调用的方法,默认是 React.createElement

                                        .tsx 文件:

                                        export const HelloWorld = () => 

                                        Hello world

                                        ;

                                        jsxFactory=“h”

                                        const preact_1 = require("preact");
                                        const HelloWorld = () => (0, preact_1.h)("div", null, "Hello");
                                        

                                        jsxFragmentFactory

                                        jsxFragmentFactory 定义了当使用 jsxFactory 时 JSX 片段工厂调用的方法

                                        tsconfig 配置

                                        { "compilerOptions": { "target": "esnext",
                                            "module": "commonjs",
                                            "jsx": "react",
                                            "jsxFactory": "h",
                                            "jsxFragmentFactory": "Fragment"
                                          }
                                        }
                                        

                                        TSX 文件

                                        import { h, Fragment } from "preact";
                                        const HelloWorld = () => ( <> 
                                        Hello
                                        );

                                        调用方法

                                        const preact_1 = require("preact");
                                        const HelloWorld = () => (0, preact_1.h)(preact_1.Fragment, null, (0, preact_1.h)("div", null, "Hello"));
                                        

                                        jsxImportSource

                                        在 TypeScript 4.1 后当使用 jsx =“react-jsx||react-jsxdev”

                                        ,声明引入 jsx 和 jsxs 工厂方法的模块

                                        TSX 文件

                                        import React from "react";
                                        function App() { return 

                                        Hello World

                                        ; }
                                        1. tsconfig 配置方式 1
                                        { "compilerOptions": { "target": "esnext",
                                            "module": "commonjs",
                                            "jsx": "react-jsx"
                                          }
                                        }
                                        

                                        ts 编译后的 js 输出内容:

                                        "use strict";
                                        var __importDefault =
                                          (this && this.__importDefault) ||
                                          function (mod) { return mod && mod.__esModule ? mod : { default: mod };
                                          };
                                        Object.defineProperty(exports, "__esModule", { value: true });
                                        const jsx_runtime_1 = require("react/jsx-runtime");
                                        const react_1 = __importDefault(require("react"));
                                        function App() { return (0, jsx_runtime_1.jsx)("h1", { children: "Hello World" });
                                        }
                                        
                                        1. tsconfig 配置方式 2
                                        { "compilerOptions": { "target": "esnext",
                                            "module": "commonjs",
                                            "jsx": "react-jsx",
                                            "jsxImportSource": "preact", //添加
                                            "types": ["preact"]
                                          }
                                        }
                                        

                                        ts 编译后的 js 输出内容:

                                        function App() { return (0, jsx_runtime_1.jsx)("h1", { children: "Hello World" });
                                        }
                                        exports.App = App;
                                        

                                        也可以通过注解的方式

                                        /**  @jsxImportSource preact*/
                                        export function App() { return 

                                        Hello World

                                        ; }

                                        moduleDetection

                                        检测模块

                                        • auto: Typescript 会检测 import/export 语句;当 module=“nodenext||node16"时会检测 package.json 中是否 type=” module ";并且当 jsx="react-jsx"会检测当前文件是否是 JSX 文件

                                        • legacy:通过 import/export 语句判断当前文件是否是模块 module

                                        • force:未声明的文件视作模块文件

                                          noLib

                                          禁用自动引入的库文件,如果设置了该选项会忽略 lib 选项的设置

                                          当使用 noLib 时需要自定义 Array, Boolean, Function, IArguments, Number, Object, RegExp, String 类型,否则 Typescript 无法编译

                                          reactNamespace
                                          target

                                          target 用来指定 ts 被编译为的 ES 版本

                                          target 的配置将会改变哪些 JS 特性会被降级,而哪些会被完整保留,用于保证代码在渲染环境中可以被正常渲染

                                          例如,目前所有主流浏览器都支持 ES6,那么我们可以设定 target 为 es6,而如果部署的环境是比较老旧的环境。例如,如果 target 是 ES5 或更低版本,箭头函数 () => this 会被转换为等价的 函数 表达式

                                          ESNext 值代表你的 TypeScript 所支持的最高版本。这个配置应当被谨慎使用,因为它在不同的 TypeScript 版本之间的含义不同,并且会导致升级更难预测

                                          lib

                                          运行时需要引入的库

                                          高级库

                                          描述
                                          ES5ES3 和 ES5 的核心功能定义
                                          ES2015ES2015 中额外提供的 API (别称 ES6) —— array.find, Promise,Proxy,Symbol,Map,Set,Reflect 等。
                                          ES6ES2015 的别名。
                                          ES2016ES2016 中额外提供的 API —— array.include 等。
                                          ES7ES2016 的别名。
                                          ES2017ES2017 中额外提供的 API —— Object.entries,Object.values,Atomics,SharedArrayBuffer,date.formatToParts,typed arrays 等。
                                          ES2018ES2018 中额外提供的 API —— async iterables,promise.finally,Intl.PluralRules,rexexp.groups 等。
                                          ES2019ES2019 中额外提供的 API —— array.flat,array.flatMap,Object.fromEntries,string.trimStart,string.trimEnd 等。
                                          ES2020ES2020 中额外提供的 API —— string.matchAll 等。
                                          ESNextESNext 中额外提供的 API —— 随着 JavaScript 的发展,这些会发生变化。
                                          DOMDOM 定义 —— window,document 等。
                                          WebWorkerWebWorker 上下文中存在的 API。
                                          ScriptHostWindows Script Hosting Systems 的 API。

                                          lib 用来指定项目中要用的库,一般在浏览器环境下不需要配置 lib,使用默认情况就好。修改库的情况,例如:

                                          程序不运行在浏览器中,因此不需要"dom"库。

                                          运行时平台提供了某些 JavaScript API 对象(也许通过 polyfill 支持),但还不支持某个 ECMAScript 版本的完整语法时。

                                          有一些 (但不是全部)对于更高级别的 ECMAScript 版本的 polyfill 或本地实现。

                                          编译和策略设置

                                          属性描述
                                          diagnostics调试时输出策略信息
                                          explainFiles打印编译相关文件名称,取值true/false
                                          extendedDiagnostics可以用于了解编译性能
                                          generateCpuProfile生成CPU运行缓慢概况
                                          listEmittedFiles打印编译生成文件名称
                                          listFiles打印编译文件名称,可以用于查看文件是否被编译
                                          traceResolution用于调试模块未被引用的原因,取值true/false

                                          项目设置

                                          属性描述
                                          composite强制执行某些约束
                                          disableReferencedProjectLoad复合项目中设置是否自动加载所有项目
                                          disableSolutionSearching复合项目是否允许跳转到引用的定义位置
                                          disableSourceOfProjectReferenceRedirect复合项目中是引用源文件还是声明文件
                                          incremental将上次编译的信息保存到磁盘文件中
                                          tsBuildInfoFile指定存储增量编译信息的文件

                                          输出格式设置

                                          属性描述
                                          noErrorTruncation没有错误信息截断,true:不截断 false:截断
                                          preserveWatchOutput每次发生变更时观察模式下是否清空历史console信息
                                          pretty编译时使用用颜色和上下文展示错误和信息

                                          完整性设置

                                          属性描述
                                          skipDefaultLibCheck用skipLibCheck代替
                                          skipLibCheck是否跳过声明文件的类型检查

                                          watchOptions 观察选项配置详解

                                          通过观察选项设置告诉编译器或语言服务应该采用哪种策略来跟踪文件和目录更改

                                          { "watchOptions": {}
                                          }
                                          
                                          属性描述
                                          watchOptions
                                          assumeChangesOnlyAffectDirectDependencies用于设置是否只有直接变更的文件或者直接引用变更文件的文件被重检测/重编译
                                          watchFile设置如何监视文件
                                          watchDirectory缺乏递归文件监视功能的系统中如何监视整个目录树的策略
                                          fallbackPolling当使用文件系统事件时,无本地轮询策略可用时的策略
                                          synchronousWatchDirectory本地不支持递归监视的平台上,同步调用回调并更新目录监视器的状态,而不是在一个小的时间内同一文件上发生多次编辑
                                          excludeDirectories设置被排除监视变更的文件夹
                                          excludeFiles设置被排除监视变更的文件

                                          watchFile

                                          设置如何监视文件

                                          • fixedPollingInterval: 固定的时间内检查几次每个文件的更改.
                                          • priorityPollingInterval: 每秒钟检查几次每个文件的更改,但是启发式方法检查某些类型文件的频率要低于其他方法
                                          • dynamicPriorityPolling: 使用动态序列,不经常修改的文件将不经常被检查
                                          • useFsEvents (the default): 对于修改的文件使用操作系统/文件系统的本地监听事件
                                          • useFsEventsOnParentDirectory: 对于修改的文件的父文件夹使用操作系统/文件系统的本地监听事件

                                            watchDirectory

                                            缺乏递归文件监视功能的系统中如何监视整个目录树的策略

                                            • fixedPollingInterval: 固定的时间内检查几次每个文件夹的更改.
                                            • dynamicPriorityPolling: 使用动态序列,不经常修改的文件夹将不经常被检查
                                            • useFsEvents (the default): 对于修改的文件夹使用操作系统/文件系统的本地监听事件

                                              fallbackPolling

                                              当使用文件系统事件时,此选项指定了当系统 用完本机文件监视器或不支持本机文件监视器时 使用的轮询策略。

                                              • fixedPollingInterval: 固定的时间内检查几次每个文件的更改.
                                              • priorityPollingInterval: 每秒钟检查几次每个文件的更改,但是启发式方法检查某些类型文件的频率要低于其他方法
                                              • dynamicPriorityPolling: 使用动态序列,不经常修改的文件将不经常被检查
                                              • synchronousWatchDirectory: 禁用文件夹延迟监视,延迟检测一般用于同时修改大量文件(node_modules变更)

                                                Type Acquisition 选项配置详解

                                                { "typeAcquisition": { "enable": false
                                                  }
                                                }
                                                

                                                类型获取选项仅对javascript项目比较重要,因为TypeScript项目需要明确定义类型

                                                属性描述
                                                typeAcquisition
                                                enablejs项目是否禁用类型自动引入
                                                includejs项目中ts需要额外指引以明确全局依赖
                                                excludejs项目中指定模块禁止引入类型
                                                disableFilenameBasedTypeAcquisition禁止根据文件名自动引入类型定义
                                                { "typeAcquisition": { "enable": false,
                                                    "include": ["jquery"],
                                                    "exclude": ["jest", "mocha"],
                                                    "disableFilenameBasedTypeAcquisition": true
                                                  }
                                                }