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

TypeScript:同时包含call signature与construct signature的类型别名失效

解决TypeScript中同时实现调用签名与构造签名的问题

你遇到的核心问题是:普通类的构造函数仅具备构造签名(通过new调用),但不具备调用签名(直接当作函数调用),所以无法匹配同时要求两种签名的PersonType类型。

解决方案1:工厂函数+类组合(类型安全)

通过Object.assign将工厂函数(实现调用签名)与类的构造能力合并,生成同时满足两种签名的对象:

interface Person2 {
  name: string;
  age: number;
}

type PersonType = {
  new(name: string, age: number): Person2;
  (name: string, age: number): Person2;
};

// 先定义实现Person2接口的类
class PersonClass implements Person2 {
  constructor(public name: string, public age: number) {}
}

// 构建符合PersonType的对象:兼具构造和调用能力
const personType: PersonType = Object.assign(
  // 实现调用签名:直接调用时返回实例
  (name: string, age: number) => new PersonClass(name, age),
  // 绑定构造签名:让new关键字指向PersonClass
  PersonClass
);

// 两种调用方式均正常工作
const john1 = new personType("John", 25);
const john2 = personType("John", 25);

console.log(john1); // { name: 'John', age: 25 }
console.log(john2); // { name: 'John', age: 25 }

解决方案2:类型断言简化实现

如果不需要严格的类型推导校验,可以直接用类型断言将工厂函数指定为PersonType,写法更简洁:

interface Person2 {
  name: string;
  age: number;
}

type PersonType = {
  new(name: string, age: number): Person2;
  (name: string, age: number): Person2;
};

class PersonClass implements Person2 {
  constructor(public name: string, public age: number) {}
}

// 用类型断言跳过类型检查,直接指定为PersonType
const personType = ((name: string, age: number) => new PersonClass(name, age)) as PersonType;

// 支持两种调用方式
const jane = new personType("Jane", 30);
const bob = personType("Bob", 28);

关键原理

  • TypeScript中,类本身是构造函数,但不能直接当作普通函数调用(除非类内部有特殊处理)。
  • 工厂函数可以实现普通调用签名,通过合并类的构造属性,就能让对象同时支持new调用和直接调用。

内容的提问来源于stack exchange,提问作者Deepak Pathak

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 20:28:07