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
相关产品推荐
相关产品推荐

