TypeScript如何为外部JavaScript模块编写类型声明文件?
给JS库写类型声明文件的正确姿势
基本逻辑
TypeScript认JS模块的类型全靠.d.ts文件,你要做的就是在声明文件里复刻JS库的导出结构,把每个导出的变量、函数、类、类型的类型信息都写清楚。
具体写法
先举个例子,假设你的js1.js是这么写的:
// js1.js export const someValue = 123; export function someFunc(arg) { return arg * 2; } export class SomeClass { constructor(name) { this.name = name; } greet() { return `Hello ${this.name}`; } } // JS里的类型标识TS不直接认,得在d.ts里重新定义 export const someTypeMarker = {};
那对应的js1.d.ts(注意文件名要和JS文件对应,放同一目录)就得这么写:
// js1.d.ts // 声明这是个模块,和JS的模块结构对齐 export declare const someValue: number; export declare function someFunc(arg: number): number; export declare class SomeClass { name: string; constructor(name: string); greet(): string; } // 定义你要导入的类型 export type SomeType = { id: number; name: string };
要注意的点
- 声明文件名最好和JS文件同名(比如
js1.js对应js1.d.ts),TS会自动关联,不用额外配置;如果放别的地方,得在tsconfig.json的typeRoots里指定路径,但直接放同一目录最省事。 - 如果JS库用的是默认导出,那声明文件里要写
export default declare ...,或者用declare module包裹(不过你这是本地JS文件,直接对应导出更简单)。 - 检查你的
tsconfig.json:allowJs设为true,module选ESNext这类支持模块的选项,毕竟你的TS代码是<script type="module">。 - 要是你在JS文件里已经用JSDoc写了类型注释,比如
/** @typedef {Object} SomeType @property {number} id @property {string} name */,那TS能直接识别,不用单独写d.ts;但JS里没写的话,就必须在d.ts里定义。
验证一下
写完声明文件后,在你的ts1.ts里导入试试:
// ts1.ts import { someValue, someFunc, SomeClass, SomeType } from "./js1.js"; const num = someValue; // TS能自动识别num是number类型 const result = someFunc(5); // 传非数字的话TS会报错 const instance = new SomeClass("Alice"); const obj: SomeType = { id: 1, name: "Bob" }; // 类型提示正常,结构不对会报错
这时候TS编译器不会瞎报错,类型提示也能正常工作。
内容的提问来源于stack exchange,提问作者JOE HUANG
相关产品推荐
相关产品推荐

