Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there anyway to do nested Pick<> types in Typescript

So I am trying to get safety on my client side GraphQL queries (so if there is a better approach to this let me know).

But what I have been doing is defining my query like this.

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 },
    );

in order to define the TenantManagePageQueryTenant type I do something like this

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

Where the base Tenant model is my GQL model type.

Is there anyway to do this kind of Pick statement but to also pick the nested properties.

something like

interface TenantManagePageQueryTenant
    extends Pick<Tenant, 'id' | 'description' | 'name' | Pick<approvedUser| 'id' | 'alias'> {}
like image 378
Robert Lemiesz Avatar asked Sep 19 '19 00:09

Robert Lemiesz


2 Answers

Similar to Colins answer, but coming at it from the opposite direction. If you have an existing interface/type you need to pick apart you can use indexes:


// 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

like image 196
Chris Avatar answered Sep 27 '22 02:09

Chris


The code posted by @Avius is on the right track, but the interface extending the intersection type generates an error. I believe you'd need to use 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

like image 28
colin moock Avatar answered Sep 27 '22 02:09

colin moock