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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 09:51:57