编程进阶网 编程进阶网
首页
  • 在线工具
  • JSON工具
  • 文本工具
  • 图片处理
  • 文档转化
  • 代码压缩
  • 加解密
  • 时间日期
  • 网络工具
  • 颜色设计
  • 二维码
  • 开发实用
  • 计算机原理
  • 操作系统
  • 网络协议
  • 数据库原理
  • 面向对象
  • 设计原则
  • 设计模式
  • 系统架构
  • 性能优化
  • 编程原理
  • 方案设计
  • 稳定可靠
  • 工程运维
  • 基础认知
  • 线性结构
  • 树与哈希
  • 工业级实现
  • 算法思想
  • 实战与综合
  • 算法题考核
  • C语言入门
  • C综合案例
  • C专栏博客
  • C标准集库
  • C++入门教程
  • C++综合案例
  • C++专栏博客
  • C++编程技巧
  • Java入门教程
  • Java综合案例
  • Java专栏博客
  • Go入门教程
  • Go综合案例
  • Go专栏博客
  • Go开发技巧
  • JavaScript入门
  • JavaScript高级
  • Android库解读
  • Android专栏
  • iOS ObjC入门
  • iOS Swift入门
  • iOS入门精通
  • Web之Html手册
  • Web之TypeScript
  • Web之Vue高级进阶
  • Linux之QML入门
  • Linux之QT核心库
  • Python教程
  • Shell&Bash教程
  • 工具脚本
  • 自动化脚本
  • 质量保障
  • 产品思考
  • 软实力
  • 开发流程
  • Git应用
  • 技术模版
  • 技术规范
  • Markdown
  • Mermaid
  • 开源协议
  • 关于我
  • 自我精进
  • 职场管理
  • 职场面试
  • 心情杂货
  • 友情链接

杨充

专注编程 · 终身学习者
首页
  • 在线工具
  • JSON工具
  • 文本工具
  • 图片处理
  • 文档转化
  • 代码压缩
  • 加解密
  • 时间日期
  • 网络工具
  • 颜色设计
  • 二维码
  • 开发实用
  • 计算机原理
  • 操作系统
  • 网络协议
  • 数据库原理
  • 面向对象
  • 设计原则
  • 设计模式
  • 系统架构
  • 性能优化
  • 编程原理
  • 方案设计
  • 稳定可靠
  • 工程运维
  • 基础认知
  • 线性结构
  • 树与哈希
  • 工业级实现
  • 算法思想
  • 实战与综合
  • 算法题考核
  • C语言入门
  • C综合案例
  • C专栏博客
  • C标准集库
  • C++入门教程
  • C++综合案例
  • C++专栏博客
  • C++编程技巧
  • Java入门教程
  • Java综合案例
  • Java专栏博客
  • Go入门教程
  • Go综合案例
  • Go专栏博客
  • Go开发技巧
  • JavaScript入门
  • JavaScript高级
  • Android库解读
  • Android专栏
  • iOS ObjC入门
  • iOS Swift入门
  • iOS入门精通
  • Web之Html手册
  • Web之TypeScript
  • Web之Vue高级进阶
  • Linux之QML入门
  • Linux之QT核心库
  • Python教程
  • Shell&Bash教程
  • 工具脚本
  • 自动化脚本
  • 质量保障
  • 产品思考
  • 软实力
  • 开发流程
  • Git应用
  • 技术模版
  • 技术规范
  • Markdown
  • Mermaid
  • 开源协议
  • 关于我
  • 自我精进
  • 职场管理
  • 职场面试
  • 心情杂货
  • 友情链接
  • README
  • Android提升进阶

  • iOS开发和进阶

  • Web开发和进阶

    • README
    • HTML工具手册

    • CSS样式与布局

    • JavaScript核心

    • TypeScript入门

      • README
      • TS类型系统基础
      • TS接口与对象类型
      • TS函数与类实战
      • TS泛型编程实战
      • TS高级类型编程
      • TS类型守卫机制
      • TS模块系统详解
      • TS工程配置实践实践
        • 1. 案例引入
          • 1.1 一个典型的 TS 项目启动问题
        • 2. tsconfig.json 核心选项
          • 2.1 项目入口:files / include / exclude
          • 2.2 extends:继承配置
          • 2.3 编译目标与模块系统
          • 2.4 输出相关
        • 3. strict 严格模式逐条拆解
          • 3.1 strict 包含的 8 个子项
          • 3.2 strictNullChecks
          • 3.3 strictFunctionTypes
          • 3.4 noImplicitAny / noImplicitReturns / noImplicitThis
          • 3.5 strictPropertyInitialization 和 noUnusedLocals/noUnusedParameters
        • 4. .d.ts 声明文件编写
          • 4.1 声明文件的三种角色
          • 4.2 为第三方库编写 .d.ts
          • 4.3 声明非代码模块
          • 4.4 发布声明文件
        • 5. Webpack 集成方案
          • 5.1 ts-loader 方案
          • 5.2 babel-loader + @babel/preset-typescript
          • 5.3 选型建议
        • 6. Vite / ESBuild 集成方案
          • 6.1 Vite 开箱即用
          • 6.2 类型检查插件
        • 7. 构建产物与发布
          • 7.1 多目标构建
          • 7.2 package.json 导出映射
        • 8. 速查表
    • Vue高级进阶

    • Web工程化实践

  • Linux应用开发

  • IoT智能硬件开发

  • Apps
  • Web开发和进阶
  • TypeScript入门
杨充
2025-06-24
目录

TS工程配置实践实践

# 08.TS工程配置实践

从 tsconfig.json 到生产构建——掌握 TS 项目工程化的完整链路:编译选项、strict 模式、声明文件、Webpack/Vite 集成。

# 1. 案例引入

# 1.1 一个典型的 TS 项目启动问题

# 你克隆了公司的前端项目,运行:
npm install
npm run dev

# 然后看到:
error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.
error TS2588: Cannot find name 'Promise'. Do you need to change your target library?

# 你打开 tsconfig.json——200 行配置,20+ 个选项
# 每个都影响编译行为,但文档分散在各处
# 本文就是你的 tsconfig 完全指南

# 2. tsconfig.json 核心选项

# 2.1 项目入口:files / include / exclude

{
  "files": [
    "src/index.ts"
  ],
  "include": [
    "src/**/*"
  ],
  "exclude": [
    "node_modules",
    "dist",
    "**/*.test.ts"
  ]
}
  • files:精确指定编译文件(一般只用于简单场景)
  • include:glob 模式,默认包含 index.ts 所在目录及子目录
  • exclude:排除文件,node_modules 默认已排除

# 2.2 extends:继承配置

// tsconfig.json
{
  "extends": "@company/tsconfig-base/tsconfig.json",
  "compilerOptions": {
    "outDir": "./dist"
  }
}

// 团队通用配置方案:
// tsconfig.base.json   ← 共享的 compilerOptions
// tsconfig.app.json    ← extends base + app 特有选项
// tsconfig.node.json   ← extends base + Node 特有选项

# 2.3 编译目标与模块系统

{
  "compilerOptions": {
    // 编译目标 JS 版本——影响语法降级和 lib 默认值
    "target": "ES2020",
    // "ES3"     // 传统浏览器
    // "ES2015"  // IE11+ 支持
    // "ES2020"  // 现代项目(可选链 & 空值合并)
    // "ESNext"  // 最新语法(依赖构建工具降级)

    // 模块系统——影响 import/export 编译方式
    "module": "ESNext",
    // "CommonJS" // Node.js 传统
    // "ESNext"   // 配合 Vite/Webpack(推荐)
    // "ES2020"   // 原生 import()

    // JSX 处理
    "jsx": "react-jsx",  // React 17+ 自动引入 jsx
    // "preserve"         // 保留 JSX 给 Babel 处理
    // "react"            // 转为 React.createElement
  }
}

# 2.4 输出相关

{
  "compilerOptions": {
    "outDir": "./dist",           // 输出目录
    "rootDir": "./src",           // 源码根目录(保持输出目录结构)
    "declaration": true,          // 生成 .d.ts 声明文件
    "declarationMap": true,       // 生成声明文件的 sourcemap
    "sourceMap": true,            // 生成 .js.map(调试用)
    "removeComments": false,      // 是否移除注释
    "noEmit": true,               // 不生成文件——仅做类型检查
  }
}

# 3. strict 严格模式逐条拆解

# 3.1 strict 包含的 8 个子项

{
  "compilerOptions": {
    "strict": true  // 等价于以下全部开启
  }
}

# 3.2 strictNullChecks

// strictNullChecks: false(危险)
let name: string = null;  // ✅

// strictNullChecks: true(安全)
let name: string = null;  // ❌
let nameOrNull: string | null = null;  // ✅ 显式联合

# 3.3 strictFunctionTypes

// 方法声明 vs 函数属性的逆变区别
interface Handler {
    // 方法声明——双向协变(宽松)
    onClick(e: MouseEvent): void;
    // 函数属性——严格逆变(安全)
    onHover: (e: MouseEvent) => void;
}

# 3.4 noImplicitAny / noImplicitReturns / noImplicitThis

// noImplicitAny: true → 禁止隐式 any
function greet(name) {   // ❌ name: implicit any
    return `Hi, ${name}`;
}

// noImplicitReturns: true → 函数所有路径必须有返回值
function isPositive(n: number) {
    if (n > 0) return true;
    // ❌ 缺少 else 返回——隐式 undefined
}

// noImplicitThis: true → 禁止隐式 any 的 this
class EventSource {
    onLoad() {
        // this 必须显式标注或通过箭头函数绑定
    }
}

# 3.5 strictPropertyInitialization 和 noUnusedLocals/noUnusedParameters

// strictPropertyInitialization: true → 类属性必须在构造器中初始化
class User {
    name: string;    // ❌ 未初始化
    age: number = 0; // ✅
    id!: number;     // ✅ 非空断言——"我来负责初始化"
}

// noUnusedLocals/noUnusedParameters: true → 未使用的变量/参数报错
function add(a: number, b: number, _unused: number): number {
    // let temp = 0;  // ❌ noUnusedLocals
    return a + b;
}

# 4. .d.ts 声明文件编写

# 4.1 声明文件的三种角色

.d.ts 文件用于:
1. 为无类型的 JS 库提供类型定义
2. 为项目的公共 API 生成类型声明
3. 全局类型扩充(declare global)

# 4.2 为第三方库编写 .d.ts

// 假设有一个 JS 库 "legacy-utils" 没有类型定义

// types/legacy-utils.d.ts
declare module "legacy-utils" {
    // 导出类
    export class Calculator {
        add(a: number, b: number): number;
        multiply(a: number, b: number): number;
    }

    // 导出函数
    export function formatDate(date: Date, format: string): string;

    // 导出常量
    export const VERSION: string;

    // 默认导出
    export default Calculator;
}

// 使用
import Calculator from "legacy-utils";
const calc = new Calculator();
calc.add(1, 2);

# 4.3 声明非代码模块

// 让 TS 识别图片、样式文件
declare module "*.css" {
    const classes: { [key: string]: string };
    export default classes;
}

declare module "*.png" {
    const src: string;
    export default src;
}

declare module "*.svg" {
    import { FC, SVGProps } from "react";
    const SVGComponent: FC<SVGProps<SVGSVGElement>>;
    export default SVGComponent;
}

# 4.4 发布声明文件

{
  "compilerOptions": {
    "declaration": true,           // 生成 .d.ts
    "declarationDir": "./dist/types", // 声明文件输出目录
    "declarationMap": true         // 声明 sourcemap(IDE 跳转到源码)
  }
}
// package.json
{
  "main": "./dist/index.js",
  "types": "./dist/types/index.d.ts"  // 指定入口声明文件
}

# 5. Webpack 集成方案

# 5.1 ts-loader 方案

// webpack.config.js
module.exports = {
    entry: "./src/index.ts",
    module: {
        rules: [
            {
                test: /\.tsx?$/,
                use: "ts-loader",
                exclude: /node_modules/
            }
        ]
    },
    resolve: {
        extensions: [".ts", ".tsx", ".js"]
    }
};

ts-loader 特点:直接使用 tsc 编译,忠实于 tsconfig,慢但类型检查完整。

# 5.2 babel-loader + @babel/preset-typescript

// webpack.config.js
module.exports = {
    module: {
        rules: [
            {
                test: /\.tsx?$/,
                use: {
                    loader: "babel-loader",
                    options: {
                        presets: [
                            "@babel/preset-env",
                            "@babel/preset-typescript"
                        ]
                    }
                }
            }
        ]
    }
};

Babel 特点:快但不做类型检查,适合开发阶段(用 tsc --noEmit 单独做类型检查)。

# 5.3 选型建议

你的场景?
├── 类型检查严格,团队不要求极速构建 → ts-loader
├── 开发体验优先(HMR 快)→ babel-loader + tsc --noEmit(CI 中检查)
└── 第三方库开发 → ts-loader(保证 .d.ts 输出正确)

# 6. Vite / ESBuild 集成方案

# 6.1 Vite 开箱即用

// vite.config.ts
import { defineConfig } from "vite";

export default defineConfig({
    // Vite 默认支持 TS——无需额外配置
    plugins: [],
    resolve: {
        alias: {
            "@": "/src"
        }
    }
});

Vite 的 TS 原理:

  1. 用 ESBuild 剥离类型(仅擦除,不做类型检查)→ 快
  2. 类型检查交给 IDE 或 tsc --noEmit --watch

# 6.2 类型检查插件

npm install -D vite-plugin-checker
import checker from "vite-plugin-checker";

export default defineConfig({
    plugins: [
        checker({
            typescript: true  // 浏览器中显示 TS 错误
        })
    ]
});

# 7. 构建产物与发布

# 7.1 多目标构建

// tsconfig.cjs.json
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "module": "CommonJS",
    "outDir": "./dist/cjs"
  }
}

// tsconfig.esm.json
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "module": "ESNext",
    "outDir": "./dist/esm"
  }
}

# 7.2 package.json 导出映射

{
  "name": "my-lib",
  "main": "./dist/cjs/index.js",
  "module": "./dist/esm/index.js",
  "types": "./dist/types/index.d.ts",
  "exports": {
    ".": {
      "import": "./dist/esm/index.js",
      "require": "./dist/cjs/index.js",
      "types": "./dist/types/index.d.ts"
    }
  }
}

# 8. 速查表

选项 推荐值 作用
target "ES2020" 编译目标 JS 版本
module "ESNext" 模块系统(配合构建工具)
strict true 全套严格检查
esModuleInterop true 兼容 CommonJS 默认导出
skipLibCheck true 跳过 .d.ts 检查(加速编译)
forceConsistentCasingInFileNames true 文件名大小写一致
declaration true 生成 .d.ts
sourceMap true 生成 sourcemap
outDir "./dist" 输出目录
rootDir "./src" 源码目录
noEmit true(纯检查) 不生成产物
jsx "react-jsx" React 17+ JSX 模式
moduleResolution "bundler"(TS5+) 模块解析策略

项目初始化速查:

npx tsc --init  # 生成 tsconfig.json 并预设常用选项

一句话总结:日常开发用 strict: true(全开),构建用 Vite/Babel(剥离类型+查错分离),发布库时带 .d.ts 文件。


专栏完结。回顾 8 篇:01.TS类型系统基础 → 02.TS接口与对象类型 → 03.TS函数与类实战 → 04.TS泛型编程实战 → 05.TS高级类型编程 → 06.TS类型守卫机制 → 07.TS模块系统详解 → 08.TS工程配置实践

上次更新: 2026/06/24, 12:59:24
TS模块系统详解
Vue3快速入门

← TS模块系统详解 Vue3快速入门→

最近更新
01
CSS选择器入门
06-23
02
CSS定位与层级
06-23
03
CSS盒模型详解
06-23
更多文章>
Theme by Vdoing | Copyright © 2019-2026 杨充 | MIT License | 鄂ICP备2024073355号-1 | 鄂ICP备2024073355号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式