如何基于泛型类的第三个构造函数参数定义TypeScript类型?
需求可行性分析与代码修正
这个需求完全可行,当前代码报错的核心问题是:TypeScript没法保证泛型参数Type的构造函数一定有第三个参数——哪怕ApiObject本身的构造函数有三个参数,但如果Type是它的子类且自定义了构造函数(比如改了参数个数),ConstructorParameters<Type>[2]就会变成不存在的类型,直接触发报错。
下面给两种可行的修正方案:
方案一:拆分泛型参数,明确构造函数约束
通过单独定义构造签名类型,强制Type的构造函数必须符合ApiObject的参数结构,同时把第三个参数的类型抽成独立泛型参数,类型推断更清晰:
type PatchableProps<T> = T extends { [k: string | number]: any } ? { [Key in keyof T]: PatchableProps<T[Key]> } : T | Patch // 定义构造签名,确保子类构造函数和ApiObject参数一致 type ApiObjectConstructor<Props> = new (something1: string, something2: string, props: Props) => ApiObject; export class CompositionResource<Props, Type extends ApiObjectConstructor<Props>> { readonly identifier: string = "ICompositionResource"; constructor(public readonly name: string, private readonly props: PatchableProps<Props>) {} } export class Patch { constructor() {} } export class ApiObject { constructor(public readonly something1: string, public readonly something2: string, public readonly props: SomeOtherProps) {} } export interface SomeOtherProps {}
方案二:直接在泛型约束中限定构造函数结构
如果不想拆分泛型参数,可以直接在Type的约束里通过构造签名推断第三个参数的类型,确保其存在:
type PatchableProps<T> = T extends { [k: string | number]: any } ? { [Key in keyof T]: PatchableProps<T[Key]> } : T | Patch export class CompositionResource<Type extends ApiObject & { // 强制构造函数有三个参数,第三个参数类型为P new (...args: [string, string, infer P]): ApiObject }> { readonly identifier: string = "ICompositionResource"; constructor(public readonly name: string, private readonly props: PatchableProps<ConstructorParameters<Type>[2]>) {} } export class Patch { constructor() {} } export class ApiObject { constructor(public readonly something1: string, public readonly something2: string, public readonly props: SomeOtherProps) {} } export interface SomeOtherProps {}
两种方案都能解决类型报错问题,且完全满足你的需求:CompositionResource的props类型会基于Type构造函数的第三个参数,自动应用PatchableProps的递归转换。
内容的提问来源于stack exchange,提问作者Markus Siebert
相关产品推荐
相关产品推荐

