如何在TypeScript中实现兼具调用与构造签名的函数
实现兼具调用与构造签名的TypeScript函数类型
TypeScript官方文档中定义了同时包含调用签名和构造签名的函数类型,但未给出具体实现方案。针对你提供的CallOrConstruct接口,以下是两种可行的实现方式:
方法一:函数内部区分调用场景
在函数内通过new.target判断当前是普通调用还是构造调用,分别返回对应类型的值,再用类型断言让TypeScript认可该函数符合接口定义:
interface CallOrConstruct { new (s: string): { s: string } (n: number): number } const fn: CallOrConstruct = function (this: unknown, arg: string | number): any { // 判断是否通过new关键字调用 if (new.target) { // 构造调用:返回指定结构的对象 return { s: arg as string }; } else { // 普通调用:返回处理后的数字 return (arg as number) * 2; } } as CallOrConstruct; // 测试调用逻辑 function invokeF(fn: CallOrConstruct) { console.log(fn(5)); // 输出 10 console.log(new fn('hello world')); // 输出 { s: 'hello world' } } invokeF(fn);
方法二:分离逻辑后合并类型
先分别实现普通调用和构造调用的逻辑,再通过Object.assign合并并断言类型,适合逻辑复杂的场景:
interface CallOrConstruct { new (s: string): { s: string } (n: number): number } // 实现普通调用逻辑 function callableFn(n: number): number { return n * 3; } // 实现构造调用逻辑 function constructableFn(this: { s?: string }, s: string) { this.s = s; } // 合并函数并断言类型 const fn: CallOrConstruct = Object.assign(callableFn, constructableFn) as CallOrConstruct; // 测试 function invokeF(fn: CallOrConstruct) { console.log(fn(5)); // 输出 15 console.log(new fn('hello world')); // 输出 { s: 'hello world' } } invokeF(fn);
关键说明
- TypeScript仅在编译阶段校验类型,运行时需自行处理两种调用场景的逻辑。
new.target是判断函数是否被new调用的标准方式,指向当前被调用的构造函数。- 类型断言(
as CallOrConstruct)用于告知编译器函数符合接口定义,避免不必要的类型报错。
内容的提问来源于stack exchange,提问作者lyc2014
相关产品推荐
相关产品推荐

