第 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/expresstsconfig.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 | 只含类型声明,不含实现 |
| @types | DefinitelyTyped,npm i -D @types/xxx |
| declare module | 为没类型的 JS 库声明模块 |
| declare global | 扩展 window、全局变量 |
| declaration | TS 源库时开启,自动生成 .d.ts |
| typeRoots | 类型包搜索根目录 |
| types | 显式列出要加载的类型包 |
动手练习
- 写一个 .d.ts:为本地
utils.js写utils.d.ts,声明 3 个函数 - declare module:为没有类型的库写
declare module 'xxx' - global 扩展:扩展
Window接口,加myApp字段
下一章:第 17 章:tsconfig 配置 →