我有一个硬类型,想出如何将类型定义为预定义对象类型中所有可能值的并集。
假设我们有一个自动生成的类型Person
,看起来像这样:
type Person = {
favouriteColor: string
age: number
female: boolean
}
[如何使用Person
类型创建等于string | number | boolean
的联合类型?
在我的用例中,类型为Person
是自动生成的。我在对象上使用Ramda的map函数,将该函数应用于该对象的每个值:
import { map } from 'ramda'
classroom.people.forEach(person =>
// Ramda’s `map` is applied to a `block` object here:
map<Person, Person>(property => {
// The type definitions for Ramda are not sufficiently strong to infer the type
// of `property`, so it needs to be manually annotated.
return someFunction(property)
}, person)
)
我正在寻找的行为实质上与keyof
等效,但据我所知TypeScript中没有valueof
。等效的实现是什么样的?
非常感谢!
编辑:通常,解决方案将由@ kaya3建议:type ValueOf<T> = T[keyof T]
。但是,仔细检查后,我的情况似乎受到以下困扰:
type PersonCommonFields = {
age: number,
name: string
}
type PersonFragment =
| { favouriteColor: string }
| { female: boolean }
| { eyeColor: Color }
| { born: Date }
type Person = PersonCommonFields & PersonFragment
在这种情况下,如上定义的ValueOf<Person>
返回number | string
,即仅返回PersonCommonFields
中的值,而忽略PersonFragment
。此示例的预期结果将是number | string | boolean | Color | Date
。
是否有其他方法可以解决这种情况?
很多(很多!)预先感谢!
我注意到,如果您将|
中的&
更改为PersonFragment
,则可以使用它(换句话说,创建单一类型而不是联合类型)。似乎您希望这些字段是可选的,是否可以将Partial
与单一类型一起使用(与使每个字段可选一样的行为)?
type PersonCommonFields = {
age: number,
name: string
}
type PersonFragment = Partial<{
favouriteColor: string,
female: boolean,
eyeColor: Color,
born: Date
}>
type Person = PersonCommonFields & PersonFragment;
type PersonTypes = Person[keyof Person]; // number | string | boolean | Color | Date
编辑:
@@ kaya3在注释中指出,当前行为是应设置PersonFragment
中的至少一个字段。如果这不是必需的,则上面的应该起作用。
假设条件实际上是仅存在1个字段,不能更多?您可以使用自定义类型XOR
1强制执行此操作,结果对象将允许您访问键。
// Note: Define these in your global typings file so they can be reused
type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never };
type XOR<T, U> = T | U extends object ? (Without<T, U> & U) | (Without<U, T> & T) : T | U;
type PersonFragment = XOR<
{ favouriteColor: string },
XOR<{ female: boolean }, XOR<{ eyeColor: Color }, { born: Date }>>
>;