You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 06:58:12