【问题标题】:Reference Complex type from union in Typescript从 Typescript 中的 union 引用 Complex 类型
【发布时间】: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.

也许是实用程序类型?

【问题讨论】:

    标签: typescript graphql-codegen


    【解决方案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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-10
      • 1970-01-01
      • 2018-01-16
      • 2020-09-11
      • 2021-12-30
      • 2014-08-18
      相关资源
      最近更新 更多