Typescript 如何从并集/交集对象类型的值生成类型?
我遇到了一个困难的类型,它想知道如何将一个类型定义为预定义对象类型中所有可能值的并集 假设我们有一个自动生成的类型Typescript 如何从并集/交集对象类型的值生成类型?,typescript,ramda.js,Typescript,Ramda.js,我遇到了一个困难的类型,它想知道如何将一个类型定义为预定义对象类型中所有可能值的并集 假设我们有一个自动生成的类型Person,如下所示: type Person={ 收藏夹颜色:字符串 年龄:数目 女:布尔 } 如何使用Person类型创建等于string | number | boolean的联合类型 在我的用例中,类型Person是自动生成的。我在对象上使用Ramda函数,将函数应用于每个对象的值: 从'ramda'导入{map} 教室.people.forEach(person=> /
Person
,如下所示:
type Person={
收藏夹颜色:字符串
年龄:数目
女:布尔
}
如何使用Person
类型创建等于string | number | boolean
的联合类型
在我的用例中,类型Person
是自动生成的。我在对象上使用Ramda函数,将函数应用于每个对象的值:
从'ramda'导入{map}
教室.people.forEach(person=>
//Ramda的“map”应用于此处的“block”对象:
映射(属性=>{
//Ramda的类型定义不足以推断类型
//,因此需要手动对其进行注释。
返回函数(属性)
},人)
)
我正在寻找的行为本质上等同于keyof
——但据我所知,TypeScript中没有valueof
。等效的实现是什么样子的
多谢各位
编辑:通常情况下,解决方案是@kaya3:
type ValueOf=T[keyof T]
建议的。然而,仔细检查后,我的情况似乎受到以下问题的困扰:
type PersonCommonFields = {
age: number,
name: string
}
type PersonFragment =
| { favouriteColor: string }
| { female: boolean }
| { eyeColor: Color }
| { born: Date }
type Person = PersonCommonFields & PersonFragment
在这种情况下,上面定义的ValueOf
返回number | string
,即只返回PersonCommonFields
中的值,忽略PersonFragment
。本例的预期结果是number | string | boolean | Color | Date
有没有其他办法来解决这种情况
很多(很多!)提前感谢 我注意到,如果您将
PersonFragment
中的|
更改为&
,它就会工作(换句话说,创建一个单一类型而不是联合类型)。似乎您希望这些字段是可选的,是否可以对单个类型使用Partial
(与仅使每个字段可选相同的行为)
1:受@Wex答案的启发,我找到了一个解决办法,虽然不完美,但目前已经足够了
graphql codegen
生成以下类型:
type PersonCommonFields = {
age: number,
name: string
}
type A = { favoriteColor: string }
type B = { female: boolean }
type C = { eyeColor: Color }
type D = { born: Date }
type PersonFragment = A | B | C | D
由此我创建了代码中使用的type Person=PersonCommonFields&PersonFragment
。理想情况下,只有最后一种类型(Person
)可以用来提出解决方案,因为随着GraphQL模式的发展,随着时间的推移,它不需要随着PersonFragment
的发展而保持最新,并在其联合中包含更多的类型(E
、F
、G
等)
但通过重新安排,我们可以做到:
type PersonFields =
| Person[keyof PersonCommonFields]
| A[keyof A]
| B[keyof B]
| C[keyof C]
| D[keyof D]
这将创建所需的类型number | string | favoriteColor | boolean | Color | Date
ValueOf=T[keyof T]
类型无法按您希望的方式为联合类型工作,因为keyof
不会分布在联合上。例如,keyof({foo:1}{bar:2})
的类型是never
而不是'foo'|'bar'
相反,我们可以使用a,它确实分布在工会上(顾名思义)
类型ValueOfUnion=T扩展推断U?永远不会
型式试验=数值单位
//测试=字符串|数字|布尔值|颜色|日期
从这个问题--你可以做
type ValueOf=T[keyof T]代码>。谢谢!这就是我使用的方法。然而,如果T
本身是不同类型的并集,它似乎没有返回正确的类型-但我将进一步研究这是否确实是正确的答案如果T
是并集时value的类型存在问题,我建议编辑该问题以询问该情况。我相信,ValueOf
解决了T
是Person
的问题。这看起来更好——仅仅是因为它是一个,你能为a
和B
写一些简单的例子,并说出你想要的结果吗?我想我有一个可行的解决方案,但最好在回答之前把问题弄清楚,以免我误解。结果证明我的想法并不直接有效,但我认为这应该是可能的。我会再仔细考虑一下。这不太一样,因为原始类型至少需要一个可选属性。我开始使用的类型是自动生成的(通过graphql codegen
),所以我必须从给定的类型开始…哎呀,我在你的问题中忽略了这一点。这个答案可能会帮助其他人,但不幸的是,它似乎对你没有任何帮助。很抱歉。
type PersonCommonFields = {
age: number,
name: string
}
type A = { favoriteColor: string }
type B = { female: boolean }
type C = { eyeColor: Color }
type D = { born: Date }
type PersonFragment = A | B | C | D
type PersonFields =
| Person[keyof PersonCommonFields]
| A[keyof A]
| B[keyof B]
| C[keyof C]
| D[keyof D]