【问题标题】:Is there anyway to do nested Pick<> types in Typescript无论如何在 Typescript 中做嵌套 Pick<> 类型
【发布时间】:2020-01-19 23:03:26
【问题描述】:

因此,我正在尝试确保客户端 GraphQL 查询的安全性(因此,如果有更好的方法,请告诉我)。

但我一直在做的是这样定义我的查询。

export const tenantManagePageQuery = async (tenantId: string) =>
    graphQLClient.request<{
        tenants: TenantManagePageQueryTenant[];
    }>(
        /* GraphQL */ `
            query tenants($tenantId: String!) {
                tenants(tenantIds: [$tenantId]) {
                    id
                    description
                    name
                    approvedUsers {
                        id
                        alias
                    }
                    pendingUsers {
                        id
                        alias
                    }
                }
            }
        `,
        { tenantId },
    );

为了定义TenantManagePageQueryTenant 类型,我做了这样的事情

interface TenantManagePageQueryTenant
    extends Pick<Tenant, 'id' | 'description' | 'name'> {}

基本租户模型是我的 GQL 模型类型。

无论如何要执行这种 Pick 语句,但还要选择嵌套属性。

类似

interface TenantManagePageQueryTenant
    extends Pick<Tenant, 'id' | 'description' | 'name' | Pick<approvedUser| 'id' | 'alias'> {}

【问题讨论】:

  • 用例是什么?您想要所有可能键的类型联合(即使嵌套在另一个键下?)
  • 我想选择一个根类型的字段,但要确保该字段中的键都是其他类型的有效键

标签: typescript graphql


【解决方案1】:

类似于科林斯的回答,但从相反的方向来。如果你有一个现有的接口/类型,你需要分开你可以使用索引:


// Existing type
type Tenant = {
    id:string;
    description:string;
    name:string;
    approvedUsers: Array<{
      id:string;
      alias:string;
    }>
}

// Pick it apart
type TenantManagePageQueryTenant = 
  Pick<Tenant, 'id' | 'description' | 'name'> & {
    approvedUsers: Array<Pick<Tenant['approvedUsers'][0], 'id' | 'alias'>>
  }

Playground

【讨论】:

  • 这正是我想要的非常感谢
【解决方案2】:

@Avius贴出的代码是在正确的轨道上,但是扩展交集类型的接口产生了错误。我相信你需要使用 type:

type TenantManagePageQueryTenant = Pick<Tenant, 'id' | 'description' | 'name'>
    & { approvedUsers: Pick<ApprovedUser, 'id' | 'alias'>[] }
{ }

interface Tenant {
    id:string;
    description:string;
    name:string;
}

interface ApprovedUser {
    id:string;
    alias:string;
}

let tenant:TenantManagePageQueryTenant = {
  id: "123",
  description: "456",
  name: "789",
  approvedUsers: [{
    id: "aaa",
    alias: "bbb" // To see the desired type warning, try removing 'alias' 
  }]
}

Playground Link

【讨论】:

    【解决方案3】:

    不完全确定我是否正确理解了这个问题,但也许交叉点类型会有所帮助?

    假设 approvedUsers 实际上是一个数组,类型可能如下所示:

    interface TenantManagePageQueryTenant extends
        Pick<Tenant, 'id' | 'description' | 'name'>
        & { approvedUsers: Pick<ApprovedUser | 'id' | 'alias'>[] }
    {}
    

    因此这将是TenantManagePageQueryTenant 类型的有效对象:

    {
      id: "123",
      description: "456",
      name: "789",
      approvedUsers: [{
        id: "aaa",
        alias: "bbb"
      }]
    }
    

    而这些不会:

    // missing alias in approvedUsers[0]
    
    {
      id: "123",
      description: "456",
      name: "789",
      approvedUsers: [{
        id: "aaa"
      }]
    }
    
    // unknown field extra in approvedUsers[0]
    {
      id: "123",
      description: "456",
      name: "789",
      approvedUsers: [{
        id: "aaa",
        alias: "bbb",
        extra: 345678
      }]
    }
    

    【讨论】:

      猜你喜欢
      • 2021-10-22
      • 1970-01-01
      • 2019-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-06
      • 2018-07-26
      相关资源
      最近更新 更多