TypeScript 配置与工程化

这一篇深入 TypeScript 的配置和工程化:tsconfig.json 详解、
编译选项、与构建工具的集成、类型声明文件。

 1{
 2  "compilerOptions": {
 3    // 编译选项
 4  },
 5  "include": [
 6    "src/**/*"
 7  ],
 8  "exclude": [
 9    "node_modules",
10    "dist"
11  ],
12  "extends": "./base.json",
13  "files": [
14    "src/index.ts"
15  ]
16}
 1// base.json
 2{
 3  "compilerOptions": {
 4    "strict": true,
 5    "target": "ES2020"
 6  }
 7}
 8
 9// tsconfig.json
10{
11  "extends": "./base.json",
12  "compilerOptions": {
13    "outDir": "./dist"
14  }
15}
 1{
 2  "compilerOptions": {
 3    // 目标版本
 4    "target": "ES2020",
 5    
 6    // 模块系统
 7    "module": "ESNext",
 8    
 9    // 库文件
10    "lib": ["ES2020", "DOM"],
11    
12    // 输出目录
13    "outDir": "./dist",
14    
15    // 根目录
16    "rootDir": "./src",
17    
18    // 输出文件
19    "outFile": "./dist/bundle.js"
20  }
21}
 1{
 2  "compilerOptions": {
 3    // 严格模式
 4    "strict": true,
 5    
 6    // 不允许隐式 any
 7    "noImplicitAny": true,
 8    
 9    // 严格的 null 检查
10    "strictNullChecks": true,
11    
12    // 严格的函数类型检查
13    "strictFunctionTypes": true,
14    
15    // 严格的 bind/call/apply 检查
16    "strictBindCallApply": true,
17    
18    // 严格的属性初始化检查
19    "strictPropertyInitialization": true,
20    
21    // 不允许 this 隐式 any
22    "noImplicitThis": true,
23    
24    // 总是使用严格模式
25    "alwaysStrict": true,
26    
27    // 不允许未使用的局部变量
28    "noUnusedLocals": true,
29    
30    // 不允许未使用的参数
31    "noUnusedParameters": true,
32    
33    // 不允许隐式返回
34    "noImplicitReturns": true,
35    
36    // 不允许 fallthrough case
37    "noFallthroughCasesInSwitch": true
38  }
39}
 1{
 2  "compilerOptions": {
 3    // 模块解析策略
 4    "moduleResolution": "node",
 5    
 6    // 基础路径
 7    "baseUrl": ".",
 8    
 9    // 路径映射
10    "paths": {
11      "@/*": ["src/*"],
12      "utils/*": ["src/utils/*"]
13    },
14    
15    // 根目录
16    "rootDirs": ["src", "generated"],
17    
18    // 类型根目录
19    "typeRoots": ["./node_modules/@types"],
20    
21    // 类型声明文件
22    "types": ["node", "jest"]
23  }
24}
 1{
 2  "compilerOptions": {
 3    // 生成声明文件
 4    "declaration": true,
 5    
 6    // 声明文件输出目录
 7    "declarationDir": "./types",
 8    
 9    // 生成 source map
10    "sourceMap": true,
11    
12    // 生成内联 source map
13    "inlineSourceMap": true,
14    
15    // 生成声明文件的 source map
16    "declarationMap": true,
17    
18    // 移除注释
19    "removeComments": true,
20    
21    // 不生成输出文件
22    "noEmit": true,
23    
24    // 增量编译
25    "incremental": true,
26    
27    // TS 构建信息文件
28    "tsBuildInfoFile": "./.tsbuildinfo"
29  }
30}
 1{
 2  "compilerOptions": {
 3    // 允许 JavaScript 文件
 4    "allowJs": true,
 5    
 6    // 检查 JavaScript 文件
 7    "checkJs": true,
 8    
 9    // JSX 模式
10    "jsx": "react",
11    
12    // 实验性装饰器
13    "experimentalDecorators": true,
14    
15    // 发出装饰器元数据
16    "emitDecoratorMetadata": true,
17    
18    // 跳过库文件类型检查
19    "skipLibCheck": true,
20    
21    // 强制文件大小写一致
22    "forceConsistentCasingInFileNames": true,
23    
24    // 解析 JSON 模块
25    "resolveJsonModule": true,
26    
27    // 隔离模块
28    "isolatedModules": true
29  }
30}
 1// webpack.config.js
 2module.exports = {
 3  entry: './src/index.ts',
 4  module: {
 5    rules: [
 6      {
 7        test: /\.tsx?$/,
 8        use: 'ts-loader',
 9        exclude: /node_modules/
10      }
11    ]
12  },
13  resolve: {
14    extensions: ['.tsx', '.ts', '.js']
15  }
16};
 1// tsconfig.json
 2{
 3  "compilerOptions": {
 4    "target": "ES2020",
 5    "module": "ESNext",
 6    "lib": ["ES2020", "DOM"],
 7    "jsx": "react",
 8    "strict": true,
 9    "esModuleInterop": true,
10    "skipLibCheck": true,
11    "forceConsistentCasingInFileNames": true
12  }
13}
 1// vite.config.ts
 2import { defineConfig } from 'vite';
 3import react from '@vitejs/plugin-react';
 4
 5export default defineConfig({
 6  plugins: [react()],
 7  resolve: {
 8    alias: {
 9      '@': '/src'
10    }
11  }
12});
 1// tsconfig.json
 2{
 3  "compilerOptions": {
 4    "target": "ES2020",
 5    "useDefineForClassFields": true,
 6    "lib": ["ES2020", "DOM", "DOM.Iterable"],
 7    "module": "ESNext",
 8    "skipLibCheck": true,
 9    "moduleResolution": "bundler",
10    "allowImportingTsExtensions": true,
11    "resolveJsonModule": true,
12    "isolatedModules": true,
13    "noEmit": true,
14    "jsx": "react-jsx",
15    "strict": true,
16    "noUnusedLocals": true,
17    "noUnusedParameters": true,
18    "noFallthroughCasesInSwitch": true
19  },
20  "include": ["src"],
21  "references": [{ "path": "./tsconfig.node.json" }]
22}
 1// rollup.config.js
 2import typescript from '@rollup/plugin-typescript';
 3
 4export default {
 5  input: 'src/index.ts',
 6  output: {
 7    file: 'dist/bundle.js',
 8    format: 'cjs'
 9  },
10  plugins: [
11    typescript({
12      tsconfig: './tsconfig.json'
13    })
14  ]
15};
 1// 全局声明
 2declare const API_URL: string;
 3declare function myGlobalFunction(): void;
 4
 5// 模块声明
 6declare module 'module-name' {
 7  export interface MyType {
 8    prop: string;
 9  }
10}
11
12// 命名空间声明
13declare namespace MyNamespace {
14  export interface MyType {
15    prop: string;
16  }
17}
1// types/my-library.d.ts
2declare module 'my-library' {
3  export function doSomething(): void;
4  export interface Config {
5    api: string;
6  }
7}
 1// types/global.d.ts
 2declare global {
 3  interface Window {
 4    myCustomProperty: string;
 5  }
 6  
 7  namespace NodeJS {
 8    interface ProcessEnv {
 9      NODE_ENV: 'development' | 'production' | 'test';
10      API_URL: string;
11    }
12  }
13}
14
15export {};
1// 扩展 Express Request
2declare namespace Express {
3  interface Request {
4    user?: {
5      id: string;
6      name: string;
7    };
8  }
9}
1project/
2├── src/
3│   ├── index.ts
4│   └── utils/
5├── dist/
6├── types/
7├── tsconfig.json
8└── package.json
 1// tsconfig.json
 2{
 3  "compilerOptions": {
 4    "composite": true,
 5    "declaration": true
 6  },
 7  "references": [
 8    { "path": "./packages/core" },
 9    { "path": "./packages/utils" }
10  ]
11}
1// packages/core/tsconfig.json
2{
3  "compilerOptions": {
4    "composite": true,
5    "declaration": true,
6    "outDir": "./dist"
7  }
8}
 1// tsconfig.dev.json
 2{
 3  "extends": "./tsconfig.json",
 4  "compilerOptions": {
 5    "sourceMap": true,
 6    "inlineSourceMap": true,
 7    "noEmit": false
 8  },
 9  "include": ["src/**/*"]
10}
 1// tsconfig.prod.json
 2{
 3  "extends": "./tsconfig.json",
 4  "compilerOptions": {
 5    "removeComments": true,
 6    "sourceMap": false,
 7    "declaration": true
 8  },
 9  "exclude": ["**/*.test.ts", "**/*.spec.ts"]
10}
1// tsconfig.test.json
2{
3  "extends": "./tsconfig.json",
4  "compilerOptions": {
5    "types": ["jest", "node"]
6  },
7  "include": ["src/**/*", "tests/**/*"]
8}
1{
2  "compilerOptions": {
3    "strict": true
4  }
5}
1{
2  "compilerOptions": {
3    "baseUrl": ".",
4    "paths": {
5      "@/*": ["src/*"]
6    }
7  }
8}
1{
2  "compilerOptions": {
3    "incremental": true,
4    "tsBuildInfoFile": "./.tsbuildinfo"
5  }
6}
 1// tsconfig.base.json
 2{
 3  "compilerOptions": {
 4    "strict": true,
 5    "target": "ES2020"
 6  }
 7}
 8
 9// tsconfig.json
10{
11  "extends": "./tsconfig.base.json",
12  "compilerOptions": {
13    "outDir": "./dist"
14  }
15}

TypeScript 的配置和工程化:

  • tsconfig.json:核心配置文件,控制编译行为
  • 编译选项:目标版本、模块系统、类型检查、输出选项
  • 构建工具集成:Webpack、Vite、Rollup 等
  • 类型声明文件:为 JavaScript 库提供类型定义
  • 项目结构:单项目和多项目结构

在实际开发中:

  • 使用严格模式提高代码质量
  • 配置路径别名简化导入
  • 启用增量编译提高构建速度
  • 分离不同环境的配置
  • 为第三方库创建类型声明