typescript - 如何从联合/交集对象类型的值中创建类型?
问题描述
我有一个很难确定如何将类型定义为预定义对象类型中所有可能值的联合的类型。
假设我们有一个自动生成的类型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
- 但据我所知valueof
,TypeScript 中没有。等效的实现会是什么样子?
非常感谢你!
编辑:通常情况下,解决方案将按照@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 }>>
>;
推荐阅读
- typescript - vscode 调试 webpack + typescript + 参考
- javascript - 如何加入 .map 和 .filter 以过滤和删除对象数组中的重复项
- google-apps-script - 需要其他用户授权的表格容器绑定脚本,即使他们是文件的编辑者或所有者
- c++ - 在 Windows 10 上成功安装后,如何让 VSCode 找到 gmp.h?
- css - 使用顺风 css 时在哪里存储自定义 css 类
- r - mgcv GAM 绘图并通过因子平滑预测
- django - 无法启动没有错误的 Django 项目
- javascript - this.$refs 在 Nuxt 应用程序中返回未定义(尝试读取 div 的高度)
- python - 连接和排序
- python - 如何在我的 Discord Music Bot 中实现队列系统?