我不确定我是否了解您在做什么,也不知道是否有可能通过继承执行任何操作,从而使子类方法参数自动与事物相交。据我所知,与您的参数相对应的通用类型如下所示:
type AllKeys<T> = T extends any ? keyof T : never;
type MakeParam<H extends Record<K,(x: any) => any>,K extends keyof any> =
{ [Q in K]: Parameters<H[Q]>[0] }[K] extends infer L ?
{ [Q in AllKeys<L>]: Extract<L,Record<Q,any>>[Q] } extends infer M ?
{ [P in K | keyof M]:
(P extends keyof M ? M[P] : unknown) &
(P extends K ? ReturnType<H[P]> : unknown)
} : never : never;
您可以这样使用它:
type Test = MakeParam<House,"wood">;
/* type Test = {
wood: Wood;
tree: string;
} */
或对于多个键,像这样的联合:
type Test2 = MakeParam<House,"wood" | "nails">;
/* type Test2 = {
wood: Wood;
nails: number & Nail[];
tree: string;
} */
请注意,number & Nail[]
。那很奇怪而且没有用,但是正是您当前代码所需要的,所以您就可以了。假定您传递给nails()
方法的对象不应具有名为nails
的键。重复项将被相交;使用风险自负。
然后,您可以像这样重构House
的定义:
class House {
constructor() {
}
wood(i: { tree: string }): Wood {
return {}
}
nails(i: { nails: number }): Nail[] {
return [{}]
}
chair(i: MakeParam<House,"wood" | "nails">): Chair {
return {}
}
diningRoom(i: MakeParam<House,"chair">): DiningRoom {
return {}
}
livingRoom(i: MakeParam<House,"chair">): LivingRoom {
return {}
}
}
我想它的工作原理与您给定的代码相同。
我想您想对MakeParam<H,K>
进行解释。那可能真的很罗word,所以我只给一个草图:
-
{ [Q in K]: Parameters<H[Q]>[0] }[K] extends infer L ? ... : never
这定义了类型L
,它是K
联合中命名的方法的所有参数的联合。当H
为House
并且K
为"wood" | "nails"
时,您得到{ tree: string } | { nails: number }
。
-
{ [Q in AllKeys<L>]: Extract<L,any>>[Q] } extends infer M ? ... : never
这定义了类型M
,该类型采用L
,并通过从所有联合件中提取所有属性将联合变成“交集”。当H
为House
而K
为"wood" | "nails"
时,您得到{ tree: string,nails: number }
。
-
{ [P in K | keyof M]: (P extends keyof M ? M[P] : unknown) & (P extends K ? ReturnType<H[P]> : unknown) }
这将创建一个具有M
中所有属性的新对象,并添加名称为K
且类型为K
的方法的返回类型的属性。通常,每个属性名称都应该只出现在K
或keyof M
中,如果我确定可以做类似M[P] | ReturnType<H[P]>
的事情(需要进行一些keyof
检查,制作该编译器),但是您的nails
定义让我暂停了一下,我必须确保它的行为与您当前的行为相同,并带有有趣的number & Nail[]
类型。
好的,希望能有所帮助。祝你好运!
Link to code
本文链接:https://www.f2er.com/3169843.html