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

如何在TypeScript中正确定义泛型构造函数类型?

修复依赖注入系统的类型定义问题

问题根源

你的类型错误源于ConstructorUnknown的定义过于严格:它被限定为无参构造函数(Constructor<object, readonly never[]>),但register函数中传入的entityConstructor是带参数的构造函数(参数类型为Instances<InputEntityConstructors>),两者的参数列表类型不兼容,导致无法直接存入Map。

修复方案

重新定义ConstructorUnknown为任意构造函数,允许它接受任意参数类型,这样就能兼容所有需要注册的构造函数。同时调整相关类型,确保整个DI系统的类型安全。

修正后的类型定义

// 通用构造函数接口,支持任意实例类型和参数列表
interface Constructor<Instance extends object, Params extends readonly unknown[]> {
  new (...args: Params): Instance
}

// 改为任意构造函数,不再限定无参
type ConstructorUnknown = Constructor<object, readonly unknown[]>

type ConstructorsUnknown = readonly ConstructorUnknown[]

// 保持Instances类型,从构造函数数组推导实例数组类型
type Instances<Constructors extends ConstructorsUnknown> = {
  readonly [Index in keyof Constructors]: InstanceType<Constructors[Index]>
}

修正后的register函数

const entityConstructorToInputEntityConstructorsMap =
  new Map<ConstructorUnknown, ConstructorsUnknown>()

function register<
  const Entity extends object,
  const InputEntityConstructors extends ConstructorsUnknown,
>(
  entityConstructor: Constructor<Entity, Instances<InputEntityConstructors>>,
  inputEntityConstructors: InputEntityConstructors,
): void {
  if (entityConstructorToInputEntityConstructorsMap.has(entityConstructor)) {
    throw new Error(`Entity "${entityConstructor.name}" is already registered`)
  }

  entityConstructorToInputEntityConstructorsMap.set(entityConstructor, inputEntityConstructors)
}

修复逻辑说明

  • ConstructorUnknown不再限制参数类型为never[],而是用unknown[]兼容任意参数列表,带参数的构造函数也能匹配该类型。
  • 泛型约束依然保留,确保entityConstructor的参数类型严格对应InputEntityConstructors的实例数组,维持类型安全。
  • 无需显式类型转换,就能直接将构造函数存入Map,彻底解决原有的类型不兼容错误。

可选优化

如果需要更精确的类型推导,可以将ConstructorUnknown改为泛型默认值,或者用Constructor<any, any>(但unknown比any更安全),上述方案已经能满足大部分DI场景的类型需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 01:48:11