====== 第十章 编译配置 ====== TypeScript编译器(tsc)提供了丰富的配置选项,通过tsconfig.json文件可以精细控制编译过程。理解这些配置选项对于构建高质量的TypeScript项目至关重要。 ===== 10.1 tsconfig.json基础 ===== ==== 10.1.1 配置文件结构 ==== { "compilerOptions": { // 编译选项 }, "include": [ // 包含的文件 ], "exclude": [ // 排除的文件 ], "extends": "./base.json", // 继承基础配置 "files": [ // 明确的文件列表 ], "references": [ // 项目引用 ] } ==== 10.1.2 配置继承 ==== // base.json { "compilerOptions": { "strict": true, "esModuleInterop": true } } // tsconfig.json { "extends": "./base.json", "compilerOptions": { "outDir": "./dist", // strict和esModuleInterop被继承 } } ===== 10.2 核心编译选项 ===== ==== 10.2.1 目标与模块 ==== { "compilerOptions": { "target": "ES2020", // 编译目标JavaScript版本 "module": "ESNext", // 模块系统 "moduleResolution": "node", // 模块解析策略 "lib": ["ES2020", "DOM"], // 包含的库类型 "jsx": "react-jsx" // JSX处理方式 } } target选项: - "ES3"(默认) - "ES5" - "ES6"/"ES2015" - "ES2016" 到 "ES2023" - "ESNext" module选项: - "CommonJS" - "AMD" - "UMD" - "System" - "ES6"/"ES2015"/"ES2020"/"ES2022"/"ESNext" - "Node16" - "NodeNext" ==== 10.2.2 严格类型检查 ==== { "compilerOptions": { "strict": true, // 启用所有严格类型检查 // 或者单独配置 "noImplicitAny": true, // 禁止隐式any "strictNullChecks": true, // 严格null检查 "strictFunctionTypes": true, // 严格函数类型 "strictBindCallApply": true, // 严格bind/call/apply "strictPropertyInitialization": true, // 严格属性初始化 "noImplicitThis": true, // 禁止隐式this "alwaysStrict": true // 始终使用严格模式 } } ==== 10.2.3 输出配置 ==== { "compilerOptions": { "outDir": "./dist", // 输出目录 "outFile": "./bundle.js", // 合并输出文件(仅限AMD/System) "rootDir": "./src", // 源代码根目录 "removeComments": true, // 移除注释 "sourceMap": true, // 生成source map "declaration": true, // 生成.d.ts声明文件 "declarationMap": true, // 生成声明文件source map "declarationDir": "./types" // 声明文件输出目录 } } ==== 10.2.4 路径与别名 ==== { "compilerOptions": { "baseUrl": ".", // 基础路径 "paths": { "@/*": ["src/*"], // 路径别名 "@components/*": ["src/components/*"], "@utils/*": ["src/utils/*"], "@shared/*": ["../shared/src/*"] // 指向外部目录 }, "rootDirs": ["src", "generated"], // 虚拟根目录 "typeRoots": ["./types", "./node_modules/@types"] } } ==== 10.2.5 JavaScript支持 ==== { "compilerOptions": { "allowJs": true, // 允许编译JavaScript文件 "checkJs": true, // 检查JavaScript文件 "maxNodeModuleJsDepth": 1, // node_modules中JS检查深度 "outDir": "./dist" }, "include": ["src/**/*"] } ===== 10.3 工程引用(Project References) ===== ==== 10.3.1 多项目配置 ==== // 根目录 tsconfig.json { "files": [], "references": [ { "path": "./src/common" }, { "path": "./src/app" }, { "path": "./src/tests" } ] } // src/common/tsconfig.json { "compilerOptions": { "composite": true, // 必须启用用于项目引用 "declaration": true, "outDir": "../../dist/common" }, "include": ["./**/*"] } // src/app/tsconfig.json { "compilerOptions": { "composite": true, "outDir": "../../dist/app" }, "references": [ { "path": "../common" } // 依赖common项目 ], "include": ["./**/*"] } ==== 10.3.2 增量编译 ==== { "compilerOptions": { "composite": true, // 项目引用必需 "incremental": true, // 增量编译 "tsBuildInfoFile": "./.tsbuildinfo" // 构建信息文件 } } ===== 10.4 高级配置 ===== ==== 10.4.1 装饰器配置 ==== { "compilerOptions": { "experimentalDecorators": true, // 启用装饰器 "emitDecoratorMetadata": true // 发出装饰器元数据 } } ==== 10.4.2 模块解析 ==== { "compilerOptions": { "moduleResolution": "node", // 或 "classic" "esModuleInterop": true, // ES模块互操作 "allowSyntheticDefaultImports": true, // 允许默认导入 "forceConsistentCasingInFileNames": true, // 强制文件名大小写一致 "resolveJsonModule": true // 允许导入JSON } } ==== 10.4.3 代码质量选项 ==== { "compilerOptions": { // 未使用代码检测 "noUnusedLocals": true, // 未使用局部变量报错 "noUnusedParameters": true, // 未使用参数报错 "noImplicitReturns": true, // 所有代码路径必须有返回 "noFallthroughCasesInSwitch": true, // 禁止switch fallthrough // 类型检查增强 "noUncheckedIndexedAccess": true, // 索引访问可能undefined "exactOptionalPropertyTypes": true, // 精确可选属性类型 "noImplicitOverride": true, // 需要override关键字 "noPropertyAccessFromIndexSignature": true, // 索引签名需要方括号 // 弃用和错误 "allowUnreachableCode": false, // 不允许不可达代码 "allowUnusedLabels": false // 不允许未使用标签 } } ==== 10.4.4 emit相关选项 ==== { "compilerOptions": { "importHelpers": true, // 从tslib导入辅助函数 "noEmitHelpers": true, // 不内联辅助函数 "downlevelIteration": true, // 降级迭代器支持 "emitBOM": false, // 不输出BOM "newLine": "lf", // 换行符 "stripInternal": true, // 不输出@internal "preserveConstEnums": false, // 是否保留const enum "isolatedModules": true // 确保文件可独立编译 } } ===== 10.5 常见配置场景 ===== ==== 10.5.1 Node.js项目 ==== // tsconfig.json { "compilerOptions": { "target": "ES2020", "module": "commonjs", "lib": ["ES2020"], "outDir": "./dist", "rootDir": "./src", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "resolveJsonModule": true, "moduleResolution": "node", "sourceMap": true, "declaration": true }, "include": ["src/**/*"], "exclude": ["node_modules", "dist", "**/*.test.ts"] } ==== 10.5.2 React项目 ==== { "compilerOptions": { "target": "ES2020", "module": "ESNext", "moduleResolution": "bundler", "jsx": "react-jsx", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "noEmit": true, // 由Vite/ webpack处理emit "isolatedModules": true, "resolveJsonModule": true }, "include": ["src"], "references": [{ "path": "./tsconfig.node.json" }] } ==== 10.5.3 库开发配置 ==== { "compilerOptions": { "target": "ES2015", "module": "ESNext", "moduleResolution": "node", "lib": ["ES2020", "DOM"], "outDir": "./dist", "rootDir": "./src", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "declaration": true, "declarationMap": true, "sourceMap": true, "inlineSources": true, "stripInternal": true, "isolatedModules": true, "noEmitOnError": true }, "include": ["src/**/*"], "exclude": ["**/*.spec.ts", "**/*.test.ts"] } ==== 10.5.4 严格模式配置 ==== { "compilerOptions": { "target": "ES2022", "module": "NodeNext", "moduleResolution": "NodeNext", "lib": ["ES2022"], "strict": true, "noImplicitAny": true, "strictNullChecks": true, "strictFunctionTypes": true, "strictBindCallApply": true, "strictPropertyInitialization": true, "noImplicitThis": true, "alwaysStrict": true, "noUnusedLocals": true, "noUnusedParameters": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, "noUncheckedIndexedAccess": true, "exactOptionalPropertyTypes": true, "noImplicitOverride": true, "noPropertyAccessFromIndexSignature": true, "allowUnreachableCode": false, "allowUnusedLabels": false, "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "skipLibCheck": true } } ===== 10.6 编译器API ===== ==== 10.6.1 程序化编译 ==== import * as ts from "typescript"; function compile(fileNames: string[], options: ts.CompilerOptions): void { const program = ts.createProgram(fileNames, options); const emitResult = program.emit(); const allDiagnostics = ts .getPreEmitDiagnostics(program) .concat(emitResult.diagnostics); allDiagnostics.forEach(diagnostic => { if (diagnostic.file) { const { line, character } = ts.getLineAndCharacterOfPosition( diagnostic.file, diagnostic.start! ); const message = ts.flattenDiagnosticMessageText( diagnostic.messageText, "\n" ); console.log( `${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}` ); } else { console.log(ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n")); } }); const exitCode = emitResult.emitSkipped ? 1 : 0; console.log(`Process exiting with code '${exitCode}'.`); process.exit(exitCode); } compile(process.argv.slice(2), { noEmitOnError: true, noImplicitAny: true, target: ts.ScriptTarget.ES5, module: ts.ModuleKind.CommonJS }); ==== 10.6.2 类型检查器 ==== import * as ts from "typescript"; function visit(node: ts.Node) { console.log(ts.SyntaxKind[node.kind]); ts.forEachChild(node, visit); } const program = ts.createProgram(["example.ts"], {}); const sourceFile = program.getSourceFile("example.ts")!; visit(sourceFile); ===== 10.7 诊断与调试 ===== ==== 10.7.1 显示配置 ==== # 显示编译器配置 tsc --showConfig # 详细输出 tsc --verbose # 跟踪解析过程 tsc --traceResolution # 显示版本 tsc --version # 显示帮助 tsc --help --all ==== 10.7.2 性能分析 ==== { "compilerOptions": { "generateTrace": "./trace", // 生成性能跟踪文件 "explainFiles": true // 解释文件包含原因 } } ===== 10.8 迁移配置策略 ===== ==== 10.8.1 渐进式严格化 ==== // 阶段1: 基本严格 { "compilerOptions": { "strict": false, "noImplicitAny": true, "strictNullChecks": false } } // 阶段2: 启用strictNullChecks { "compilerOptions": { "strict": false, "noImplicitAny": true, "strictNullChecks": true } } // 阶段3: 完全严格 { "compilerOptions": { "strict": true } } ===== 10.9 小结 ===== TypeScript编译配置是项目构建的基础,关键要点包括: 1. **基础配置**:target、module、strict三大核心选项 2. **路径配置**:paths和baseUrl简化模块导入 3. **工程引用**:composite和references实现大型项目构建优化 4. **严格模式**:strict家族选项确保类型安全 5. **代码质量**:未使用检测、隐式返回检查等提升代码质量 6. **项目场景**:根据Node.js、React、库开发等不同场景选择合适配置 合理配置tsconfig.json可以显著提升开发体验和代码质量,建议新项目直接使用严格模式配置。