从 Typescript 中的 union 引用 Complex 类型
Posted
技术标签:
【中文标题】从 Typescript 中的 union 引用 Complex 类型【英文标题】:Reference Complex type from union in Typescript 【发布时间】:2020-10-02 11:28:11 【问题描述】:我正在使用 graphql-codegen
从我的 graphQL 查询中生成类型。
当涉及unions
时,结果有时会非常复杂。
这是一个具体的例子
export type GroupQuery = __typename?: 'Query' &
group?: Maybe<
__typename?: 'Group' & Pick<
Group,
'id' | 'name'
> &
criterions: Array<
__typename?: 'kindA' & Pick<SomeModel, 'id' | 'type'> |
__typename?: 'kindB' & Pick<SomeOtherModel, 'id' | 'type' | 'count'>
>
所以我想做的是能够参考基于__typename
的联合的具体案例
let kindB: NonNullable<GroupQuery['group']>['criterions'][0]// not sure where to go from here.
也许是实用程序类型?
【问题讨论】:
【参考方案1】:这种类型:
type T = NonNullable<GroupQuery['group']>['criterions'][0]`
将被解析为这种类型:
type T =
__typename?: "kindA" | undefined;
id: number;
name: string;
|
__typename?: "kindB" | undefined;
id: number;
name: string;
那么你真正要问的是如何在哪里获得工会的分支:
__typename === 'kindB'
在这种情况下,您可以使用交集&
来过滤联合类型。一般情况下是这样的:
type T = ("A" | "B" | "C") & "A" // "A"
Playground
因此,您可以使用交集使并集仅解析为可以匹配相交类型的类型。
type KindB =
NonNullable<GroupQuery['group']>['criterions'][0] & __typename: 'kindB'
现在KindB
解析为这种类型:
type KindB =
__typename?: "kindB" | undefined;
id: number;
name: string;
&
__typename: 'kindB';
如您所见,联合的kindA
成员不再存在,联合的其余成员正在与 __typename: 'kindB'
相交。如果你应用那个交集,它会减少到:
type KindB =
__typename: "kindB";
id: number;
name: string;
Playground with working code
通过一些重构,您甚至可以使用一个不错的泛型类型别名来使它变得非常好:
// Union of all criterion types
type GroupQueryCriterions =
NonNullable<GroupQuery['group']>['criterions'][number]
// Get the branch of the criterions union that has a specific typename.
type GroupQueryCriterionType<T extends GroupQueryCriterions['__typename']> =
GroupQueryCriterions & __typename: T
// Get a specific criterion type.
type KindB = GroupQueryCriterionType<'kindB'>
Playground
【讨论】:
以上是关于从 Typescript 中的 union 引用 Complex 类型的主要内容,如果未能解决你的问题,请参考以下文章
[TypeScript] Union Types and Type Aliases in TypeScript
typescript discriminated_union.ts
[TypeScript] Typescript Interfaces vs Aliases Union & Intersection Types