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

TypeScript:如何实现含调用与构造签名的接口?能否创建实例?

在TypeScript中实现含调用签名与构造签名的接口

首先,你定义的接口I要求对象同时具备两种核心能力:

  • 直接调用((): string):像普通函数一样执行,返回字符串
  • 构造调用(new(): any):用new关键字实例化,返回任意类型的对象

实现方法

在JavaScript中,函数本身既是可调用的,又可以作为构造函数(通过new调用),我们可以利用这一特性来实现该接口,主要有两种实用方式:

1. 直接编写函数表达式(结合类型标注)

我们可以写一个函数,通过new.target判断调用方式,分别返回对应结果,然后将其标注为接口I的类型:

interface I {
  (): string;
  new(): any;
}

const myImplementation: I = function() {
  // 判断是否通过new关键字调用
  if (new.target) {
    // 构造调用场景:返回任意结构的对象(满足new(): any的要求)
    return { id: 1, name: "instance" };
  } else {
    // 直接调用场景:返回字符串(满足(): string的要求)
    return "Hello from direct function call!";
  }
};

// 验证调用逻辑
console.log(myImplementation()); // 输出: "Hello from direct function call!"
const instance = new myImplementation(); // instance为any类型,符合接口要求

2. 结合类与函数包装(适合复杂构造逻辑)

如果你的构造实例需要复杂的初始化逻辑,可以先定义一个类,再用函数包装实现两种调用方式:

interface I {
  (): string;
  new(): any;
}

// 定义构造调用时返回的类
class MyInstance {
  public createdAt: Date;
  constructor() {
    this.createdAt = new Date();
  }
}

const myImplementation: I = function() {
  if (new.target) {
    // 构造调用时返回类的实例
    return new MyInstance();
  } else {
    // 直接调用时返回字符串
    return "Hello from wrapped function!";
  }
};

// 验证逻辑
console.log(myImplementation()); // 输出: "Hello from wrapped function!"
const instance = new myImplementation();
console.log(instance.createdAt); // 输出当前时间

关键注意事项

  • 不能直接用类实现该接口:类的实例是对象,无法满足“直接调用”的函数签名;而类的构造函数本身在严格模式下不允许直接调用,因此无法同时适配两种签名要求。
  • new.target是核心判断依据:这是ES6引入的特性,能精准区分函数是直接调用还是通过new调用,让我们在同一个函数体内处理两种逻辑。

内容的提问来源于stack exchange,提问作者Radu Szasz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 07:50:12