无论如何在打字稿中做嵌套的 Pick<> 类型

Rob*_*esz 8 typescript graphql

所以我试图在我的客户端 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 },
    );

Run Code Online (Sandbox Code Playgroud)

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

interface TenantManagePageQueryTenant
    extends Pick<Tenant, 'id' | 'description' | 'name'> {}
Run Code Online (Sandbox Code Playgroud)

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

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

就像是

interface TenantManagePageQueryTenant
    extends Pick<Tenant, 'id' | 'description' | 'name' | Pick<approvedUser| 'id' | 'alias'> {}
Run Code Online (Sandbox Code Playgroud)

Chr*_*ris 27

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


// 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'>>
  }
Run Code Online (Sandbox Code Playgroud)

替代方案 1 - 提取类型

正如评论中指出的,这可以稍微干净一些:

type TenantSubset = Pick<Tenant, 'id' | 'description' | 'name'>
type ApprovedUserSubset = Pick<Tenant['approvedUsers'][number], 'id' | 'alias'>

type TenantManagePageQueryTenant = TenantSubset & { approvedUsers: Array<ApprovedUserSubset> }
Run Code Online (Sandbox Code Playgroud)

替代方案 2 - 无拣选

这个版本虽然有点重复,但(主观上)更容易阅读:

type TenantManagePageQueryTenant = { 
  id: Tenant['id'],
  description: Tenant['description'],
  name: Tenant['name'],
  approvedUsers: Array<{
    id: Tenant['approvedUsers'][number]['id'],
    alias: Tenant['approvedUsers'][number]['alias'],
  }> 
}

Run Code Online (Sandbox Code Playgroud)

操场

  • 这正是我想要的 非常感谢 (2认同)

col*_*ock 5

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

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' 
  }]
}
Run Code Online (Sandbox Code Playgroud)

游乐场链接