← 返回题目列表

TypeScript 声明文件 .d.ts 有什么作用?

高频 中等 第 15 / 32 题 更新于 2026/07/29
TypeScriptd.ts类型声明

简化版

.d.ts 声明文件用来描述已有 JavaScript 代码或第三方库的类型形状,只提供类型信息,不提供运行时实现。它让 TypeScript 在不改 JS 源码的情况下获得类型检查和智能提示。

详细版

声明文件常见用途:

  • 给纯 JavaScript 库补类型。
  • 描述全局变量、全局函数。
  • 声明 CSS Module、图片等非 TS 模块。
  • 扩展已有模块类型。

示例:

declare module '*.module.css' {
  const classes: Record<string, string>;
  export default classes;
}

面试重点是:.d.ts 没有实现,只描述类型契约。

完整版教学

一、声明文件解决类型信息缺失问题

TypeScript 需要知道一个模块导出了什么、函数参数是什么、返回值是什么。 如果代码本身是 JavaScript,或者导入的是图片、CSS、全局 SDK,TS 默认可能不知道类型。 .d.ts 就是给这些运行时实体补一份类型说明书。

declare function track(event: string, payload?: object): void;

这行声明告诉 TS:运行时有一个 track 函数。 但它不会创建这个函数。 如果运行时没有真实 track,代码依然会报运行时错误。

二、declare 表示“外部已经存在”

declare 的意思是声明某个东西存在。 它只进入类型系统,不生成 JavaScript。 这很适合描述 CDN 注入的全局对象或宿主环境 API。

declare const APP_VERSION: string;

console.log(APP_VERSION);

流程如下:

构建或运行环境注入 APP_VERSION
  -> .d.ts 告诉 TS 它是 string
  -> 业务代码获得类型检查

如果只写声明,不做实际注入,浏览器里仍然会出现 ReferenceError

三、声明模块能处理特殊导入

前端项目经常导入 CSS、图片、SVG。 这些文件不是 TypeScript 模块,但打包器能处理。 声明文件可以告诉 TS 这些导入的类型。

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

declare module '*.module.css' {
  const classes: Record<string, string>;
  export default classes;
}
导入资源常见类型
.png/.jpgstring URL
.module.cssRecord<string, string>
.svg?component组件类型
.json由配置或推断决定

这类声明要和构建工具的真实行为一致。

四、第三方库类型从哪里来

很多库自带类型声明。 如果库没有自带声明,可以安装 @types/xxx。 再不行,项目里可以自己写局部声明。

npm install -D @types/lodash

TypeScript 会按配置和模块解析规则寻找声明文件。 常见位置包括包里的 types 字段、index.d.tsnode_modules/@types。 这也是为什么安装类型包后 IDE 立刻有提示。

五、模块扩展可以补充已有类型

声明文件还能做 module augmentation。 例如给第三方库的接口补字段,或者给 Express Request 扩展用户信息。 这在中后台和 Node 项目里很常见。

declare module 'some-lib' {
  interface Options {
    traceId?: string;
  }
}

记忆钩子:.d.ts 是类型世界的合同,不是运行时代码的施工队。

扩展类型时要确保模块名写对。 否则声明不会合并到目标模块,可能变成一个新的无效声明。

六、写声明文件要避免 any 泛滥

有些同学为了让报错消失,会写 declare module 'xxx';。 这会把模块变成 any,短期安静,长期失去类型保护。 更好的做法是先声明常用 API,再逐步补全。

declare module 'legacy-lib' {
  export function request(url: string): Promise<unknown>;
}

数字上看,先覆盖 3 个常用函数,比把整个库声明成 any 更有价值。 类型声明是边用边补的契约,不必一次完美,但不能完全放弃。

七、常见误区与追问

  • 误区:.d.ts 会生成运行时代码。 声明文件只提供类型信息,不会生成实现。
  • 误区:写了 declare 就能保证变量运行时存在。 declare 只是告诉 TS 外部存在,真实值仍要由环境提供。
  • 误区:没有类型的库直接 declare module 就完事。 这样通常会退化成 any,应该尽量补出关键 API 类型。
  • 追问:@types 包有什么作用? 它为没有内置类型的第三方库提供类型声明。
  • 追问:CSS Module 为什么要声明? TS 不认识 CSS 文件导入,需要声明模块形状,打包器负责运行时处理。
  • 追问:模块扩展有什么风险? 模块名写错或扩展位置不被 tsconfig 包含,声明就不会生效。

八、加强记忆

声明文件就记“只描述,不实现”。它描述全局变量、第三方库、特殊资源导入和模块扩展。回答时一定补运行时边界:.d.ts 让 TS 相信某东西存在,但真正存在要靠脚本、打包器或运行环境。