Skip to content
第 16 章 前端 ⏱ 11 分钟阅读

第 16 章:声明文件 ​

学习目标 ​

  • 学会编写 .d.ts 声明文件
  • 理解 @types/xxx 的工作原理
  • 掌握模块声明、UMD、全局扩展
  • 学会为 JS 库补充类型

一、什么是声明文件 ​

.d.ts 文件只包含类型信息,不包含实现。

typescript
// math.d.ts
export function add(a: number, b: number): number;
export const PI: number;

⚠️ 坑 1:声明文件不能有运行时代码,只能声明类型、变量、函数签名。

二、@types/xxx 是什么 ​

DefinitelyTyped 仓库提供第三方 JS 库的类型定义:

bash
npm install --save-dev @types/lodash
npm install --save-dev @types/node
npm install --save-dev @types/express

tsconfig.json:

json
{
  "compilerOptions": {
    "types": ["node", "lodash"]
  }
}

三、为 JS 库补充类型 ​

假设有这样一个老 JS 文件:

javascript
// math.js
export function add(a, b) { return a + b; }
export const PI = 3.14;

新建 math.d.ts:

typescript
export function add(a: number, b: number): number;
export const PI: number;

现在 TS 项目里就可以用类型了:

typescript
import { add, PI } from './math';
add(1, 2);   // ✅ 类型检查
PI;          // ✅ number

四、模块声明(给已有库加类型) ​

typescript
// types.d.ts
declare module 'my-lib' {
  export function greet(name: string): string;
  export const version: string;
}

使用:

typescript
import { greet } from 'my-lib';
greet('Tom');  // ✅

⚠️ 坑 2:declare module 只声明类型,运行时要确保 my-lib 真有 greet 函数(否则运行时找不到)。

五、全局声明(扩展 window) ​

typescript
// global.d.ts
export {};

declare global {
  interface Window {
    myApp: {
      version: string;
      track(event: string): void;
    };
  }
}

// 直接使用,不需要 import
window.myApp.version;  // ✅
window.myApp.track('click');  // ✅

六、UMD 库声明 ​

老库同时支持 CommonJS、AMD、全局变量:

typescript
export function add(a: number, b: number): number;

export as namespace myLib;

七、为类补充私有字段 ​

typescript
declare namespace Express {
  interface Request {
    user?: { id: string };
  }
}
typescript
app.use((req, res, next) => {
  if (req.user) {
    console.log(req.user.id);  // ✅
  }
});

八、自动生成声明文件 ​

如果库本身就是 TS 写的:

json
// tsconfig.json
{
  "compilerOptions": {
    "declaration": true,
    "declarationDir": "./dist/types",
    "outDir": "./dist"
  }
}

tsc 会自动生成 .d.ts。

⚠️ 坑 3:开 declaration: true 后,任何类型错误都会让编译失败,CI 必备。

九、实战:为工具库写 .d.ts ​

javascript
// utils.js
export function format(date, fmt = 'YYYY-MM-DD') { /* ... */ }
export function parse(str) { /* ... */ }
typescript
// utils.d.ts
export function format(date: Date, fmt?: string): string;
export function parse(str: string): Date;

十、typeRoots 与 types ​

json
{
  "compilerOptions": {
    "typeRoots": ["./node_modules/@types", "./src/types"],
    "types": ["node", "lodash"]
  }
}
  • typeRoots:去哪里找类型声明包
  • types:哪些包自动加载(留空表示全部)

⚠️ 坑 4:types 留空是"全部加载",项目一大可能导致类型冲突。建议显式列出。

十一、本章小结 ​

要点关键
.d.ts只含类型声明,不含实现
@typesDefinitelyTyped,npm i -D @types/xxx
declare module为没类型的 JS 库声明模块
declare global扩展 window、全局变量
declarationTS 源库时开启,自动生成 .d.ts
typeRoots类型包搜索根目录
types显式列出要加载的类型包

动手练习 ​

  1. 写一个 .d.ts:为本地 utils.js 写 utils.d.ts,声明 3 个函数
  2. declare module:为没有类型的库写 declare module 'xxx'
  3. global 扩展:扩展 Window 接口,加 myApp 字段

下一章:第 17 章:tsconfig 配置 →

本站基于 VitePress 构建 · 由 StackHub 团队维护