从 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'

在这种情况下,您可以使用交集&amp; 来过滤联合类型。一般情况下是这样的:

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

Typescript:使用UNION运算符时出错

Typescript Unions 接口和原语

Typescript - 从基类中的静态方法实例化子类,使用 args 并引用其他静态方法