首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何从联合/交叉对象类型的值中创建类型?

如何从联合/交叉对象类型的值中创建类型?
EN

Stack Overflow用户
提问于 2020-02-05 22:22:18
回答 2查看 324关注 0票数 1

我有一个困难的类型,想出如何将类型定义为来自预定义对象类型的所有可能值的合并。

假设我们有一个自动生成的类型Person,如下所示:

代码语言:javascript
运行
复制
type Person = {
  favouriteColor: string
  age: number
  female: boolean
}

如何使用Person类型创建与string | number | boolean相等的联合类型

在我的用例中,Person类型是自动生成的。我在对象上使用Ramda的地图函数,将一个函数应用于每个对象的值:

代码语言:javascript
运行
复制
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 - but在TypeScript中没有valueof。等效的实现是什么样子的?

非常感谢!

编辑:通常情况下,解决方案将如@kaya3 3:type ValueOf<T> = T[keyof T]所建议的那样。然而,仔细观察后,我的情况似乎受到以下情况的困扰:

代码语言:javascript
运行
复制
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

会否有另一种方法来处理这种情况?

很多(很多!)提前谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-02-06 01:45:55

对于联合类型,ValueOf<T> = T[keyof T]类型不能正常工作,因为keyof不会在联合中分发。例如,keyof ({foo: 1} | {bar: 2})类型是never而不是'foo' | 'bar'

相反,我们可以使用分布条件类型,它确实分布在联合中(顾名思义)。

代码语言:javascript
运行
复制
type ValueOfUnion<T> = T extends infer U ? U[keyof U] : never

type Test = ValueOfUnion<Person>
// Test = string | number | boolean | Color | Date

操场连接

票数 1
EN

Stack Overflow用户

发布于 2020-02-05 23:38:21

受到@Wex的回答的启发,我找到了一个解决办法,这不是完美的,但目前已经足够了。

graphql-codegen生成以下类型:

代码语言:javascript
运行
复制
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)才能用来提出解决方案,因为它不需要随着PersonFragment的发展而与之保持最新的关系,并且在它的联合中包含更多的类型(EFG等)。随着时间的推移,随着GraphQL模式的发展。

但只要稍微调整一下,我们就能得到这样的结果:

代码语言:javascript
运行
复制
type PersonFields =
  | Person[keyof PersonCommonFields]
  | A[keyof A]
  | B[keyof B]
  | C[keyof C]
  | D[keyof D]

它创建所需的类型number | string | favoriteColor | boolean | Color | Date

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60084968

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档