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

TypeScript中定义Constructor<T>约束构造函数参数时的类型校验异常问题

问题解答:为什么TypeScript允许传入不符合签名的构造函数?

这不是TypeScript的Bug,而是因为你当前的Constructor<T>类型定义没有严格限制构造函数的参数个数,再结合TypeScript对类隐式构造函数的类型处理逻辑,才出现了这个情况。

为什么当前代码没有报错?

当你不给类定义显式构造函数时,TypeScript会自动生成一个隐式构造函数,它的类型被推断为new (...args: any[]) => T——简单来说,这个构造函数可以接受任意数量、任意类型的参数(毕竟在JavaScript里,调用构造函数时传入多余参数本来就是合法的,只是会被构造函数忽略)。

你的原Constructor<T>类型定义是:

type Constructor<T> = new (struct: Struct<T>) => T;

这个类型只要求构造函数能接收一个Struct<T>类型的参数,但new (...args: any[]) => T完全满足这个条件(你可以传入一个Struct<T>参数,构造函数大不了忽略它)。所以TypeScript认为typeof MagicMonkey和Constructor<MagicMonkey>是兼容的,自然不会报错。

你提到的“类型定义能强制函数内部写new Constructor(struct)而非new Constructor()”,是因为在createObjectIntance函数内部,TypeScript是基于Constructor<T>的类型做检查的——这个类型明确要求构造函数需要一个参数,所以写new Constructor()会触发类型错误,这部分逻辑是符合预期的。

如何让TypeScript强制要求构造函数必须显式接收Struct<T>参数?

要解决这个问题,你需要修改Constructor<T>的定义,让它严格限制构造函数的参数列表恰好只有一个Struct<T>类型的参数,而不是允许任意参数。可以通过元组类型来实现:

type PropertyNames<T> = { [K in keyof T]: T[K] extends Function ? never : K; }[keyof T];
type Struct<T> = Pick<T, PropertyNames<T>>;
// 使用元组类型强制参数个数为1,且类型必须是Struct<T>
type Constructor<T> = new (...args: [Struct<T>]) => T;

class MagicMonkey {
  age: number;
  name: string;
  fly() { }
  // 现在必须显式定义符合要求的构造函数,否则调用createObjectIntance会报错
  constructor(struct: Struct<MagicMonkey>) {
    this.age = struct.age;
    this.name = struct.name;
  }
}

function createObjectIntance<T>(Constructor: Constructor<T>, struct: Struct<T>): T {
  return new Constructor(struct);
}

// 现在正常工作
const jack: MagicMonkey = createObjectIntance(MagicMonkey, { name: 'jack', age: 1000})
console.log(jack)

现在,如果MagicMonkey没有显式定义接收Struct<MagicMonkey>的构造函数,TypeScript会直接抛出类型错误,完全符合你的预期。

内容的提问来源于stack exchange,提问作者Marthinus Engelbrecht

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 19:37:35