typescript - 使用特殊方法减少类中的输入
问题描述
我正在寻找一种减少打字稿打字冗余的方法。我正在创建一个特定类型的类,其中:
- 类中的每个方法都有一个参数
- 每个参数key都有对应的方法
- 此方法中也允许来自相应方法的参数(仅第一个)。
这是一个类的工作示例:
interface Wood {}
interface Chair {}
interface DiningRoom {}
interface LivingRoom {}
interface Nail {}
class House {
constructor () {
}
wood (i: {tree: string}): Wood {
return {}
}
nails (i: {nails: number}): Nail[] {
return [{}]
}
chair (i: {wood: Wood, nails: Nail[]}
& Parameters<House['wood']>[0]
& Parameters<House['nails']>[0]
): Chair {
return {}
}
diningRoom (i: {chair: Chair } & Parameters<House['chair']>[0]): DiningRoom {
return {}
}
livingRoom (i: {chair: Chair } & Parameters<House['chair']>[0]): LivingRoom {
return {}
}
}
我正在寻找可以减少编写冗余的抽象类或泛型类型& Parameters<House['wood']>[0]
。理想情况下是一个抽象类,可以将其i: {chair: Chair}
视为参数并知道要添加& Parameters<House['chair']>[0]
解决方案
我不确定我是否理解您在做什么,而且我不知道是否可以通过继承来做任何事情,从而使子类方法参数可以自动与事物相交。据我所知,与您的参数对应的泛型类型如下所示:
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>
。这可能会变得非常罗嗦,所以我只想给出一个草图:
{ [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, Record<Q, 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
,并添加名称为 inK
和类型的属性作为由 命名的方法的返回类型K
。通常,每个属性名称都应该只出现在K
orkeyof M
中,如果我确定我会做类似的事情M[P] | ReturnType<H[P]>
(通过一些keyof
检查来制作那个编译器),但是你的nails
定义让我暂停了,我必须确保它的行为和你现在的一样,有趣的number & Nail[]
类型出来了。
好的,希望有帮助。祝你好运!
推荐阅读
- java - 将值分配给数组会引发错误
- laravel - Laravel + Vuejs:使表格行中的所有文本颜色为红色/文本危险
- windows - 无法使用 dependency-check-sonar-plugin 获取 html 生成的报告
- vb.net - IEproxy 用户 + 通过身份验证
- reactjs - ReactJs 错误更新对象中的数组索引
- javascript - 如何从某个索引点向后循环数组
- javascript - Javascript Regex 仅删除标签
- asp.net - 'stock' 附近的语法不正确
- javascript - Highcharts 和 highmaps 插件渲染空白地图
- javascript - 以字符串格式提供时刻时的 ISO 格式弃用警告