如何在TypeScript中为带静态成员的函数添加类型定义?
在TypeScript中为带静态成员的函数添加类型定义
你说的这种「函数本身可调用,同时挂载静态成员」的场景在JavaScript里确实很常见,比如你写的createSpy返回的间谍函数,就同时具备调用能力和callCount属性。要在TypeScript的声明文件(.d.ts)里给这类对象做正确的类型定义,核心思路是定义一个同时兼具函数类型和对象属性的交叉类型——毕竟TS里的函数类型可以和对象类型通过交叉操作符&合并在一起。
下面是具体的实现方案:
1. 定义泛型的Spy类型
如果你希望Spy能严格继承原函数的参数和返回值类型,可以用泛型来实现:
// library.d.ts // 定义Spy类型:既是原函数类型T,又拥有callCount属性 type Spy<T extends (...args: any[]) => any> = T & { callCount: number; }; // 声明createSpy函数:接受任意函数fn,返回对应的Spy类型 declare function createSpy<T extends (...args: any[]) => any>(fn: T): Spy<T>;
这个定义的好处是类型会自动推断:当你传入一个特定类型的函数时,返回的Spy会继承它的参数和返回值约束,调用时能获得精准的类型提示。
2. 验证你的示例代码
用上面的类型定义,你的示例代码就能完美通过类型检查:
// 假设myUtil是一个已定义的工具函数 const myUtil = (name: string) => `Hello, ${name}`; // 这里可以手动指定类型,也可以让TS自动推断 const mySpy: Spy<typeof myUtil> = createSpy(myUtil); mySpy("Alice"); // 类型检查通过,参数符合myUtil的要求 console.log(mySpy.callCount === 1); // 类型检查通过,callCount被识别为number类型
3. 简化版(无需精确函数类型)
如果不需要严格对应原函数的参数和返回值,也可以直接定义一个通用的Spy类型:
type Spy = ((...args: any[]) => void) & { callCount: number; }; declare function createSpy(fn: (...args: any[]) => void): Spy;
这种方式更简洁,适合对原函数类型要求不高的场景。
本质上,TS的交叉类型就是用来处理这种「一个值同时属于多种类型」的场景,刚好匹配你这种函数+静态成员的JS模式,不管是在声明文件还是TS项目内部都能很好地工作。
内容的提问来源于stack exchange,提问作者oligofren
相关产品推荐
相关产品推荐

