为纯 javascript 第三方库补全类型提示需编写.d.ts声明文件,核心是用declare module定义模块结构、支持全局声明和类型导出,并注意导出方式、索引签名、泛型及标准类型复用,最后通过definitelytyped或包内types字段发布。

为纯 JavaScript 第三方库补全类型提示,核心是编写一个 .d.ts 声明文件,告诉 TypeScript 这个库的结构、导出内容和类型信息。它不包含运行时代码,只提供类型契约。
声明文件的基本结构与语法
.d.ts 文件本质是类型定义的“说明书”。常见写法有三种:
-
全局声明:用
declare直接声明变量、函数或类,适用于挂载在全局(如window)或通过<script></script>引入的库。例如:
declare const $: (selector: string) => any; -
模块声明:用
declare module 'xxx'包裹整个模块接口,适用于 CommonJS/ESM 模块化引入的库。这是最常用的方式。 -
类型导出:用
export或export default显式导出类型或值,让其他文件能import使用。
为 JS 库手动编写 d.ts 的步骤
以一个无类型提示的轻量库 my-utils 为例(仅导出两个函数:formatDate 和 deepClone):
- 创建同名文件
my-utils.d.ts,放在项目src/@types或node_modules/my-utils下(推荐前者) - 使用
declare module定义模块结构:
declare module 'my-utils' {
export function formatDate(date: Date | string, fmt: string): string;
export function deepClone(obj: T): T;
} - 若库支持 UMD/全局模式,可同时补充全局声明:
declare global {
const myUtils: typeof import('my-utils');
}
提升声明质量的关键细节
好的声明不只是“能用”,还要准确、可维护、兼容多种用法:
-
区分默认导出与命名导出:检查库实际导出方式(
module.exports = xxxvsexports.xxx = ...),决定用export default还是export const xxx -
处理动态属性或任意键:对类似
config.xxx的配置对象,用索引签名:[key: string]: string | number -
利用泛型和重载增强提示精度:比如
deepClone返回值应保留原类型,需泛型参数;多个调用签名可用函数重载模拟 -
引用已有类型:优先复用
lib.dom.d.ts、lib.es2020.d.ts中的标准类型(如Document、Promise),避免重复定义
发布与使用声明文件
本地开发时,只需将 .d.ts 放在 src/@types 目录下,TypeScript 会自动识别。若想共享给社区:
- 提交到 DefinitelyTyped(主流做法)
- 或在库自身
package.json中设置"types": "index.d.ts",并随包一起发布 - 使用时无需额外配置,
npm install my-utils后,TypeScript 自动加载类型(前提是声明文件路径正确且未被exclude)











