mwarger
mwarger

Reputation: 857

How to extract type from nested array in type declaration?

I have a generated type that looks like this:

export type GetUserWithMembershipsQuery = {
  getUser: {
    __typename: 'User';
    id: string;
    memberships: {
      __typename: 'ModelUserMembershipConnection';
      items: Array<{
        __typename: 'UserMembership';
        id: string;
        createdOnDate: string | null;
        renewedOnDate: string | null;
        expiresOnDate: string | null;
        membershipPhotoFileName: string | null;
      } | null> | null;
    } | null;
  } | null;
};

I know I can get the type of the getUser by saying GetUserWithMembershipQuery['getUser'].

I'm wondering how I can extract the type of the items array within the memberships object from within that type, or if it's possible?

I would like to end up with something like:

type ItemType = GetUserWithMembershipQuery['getUser']['memberships']['items'][0]

Where the resulting type is:

{
  __typename: 'UserMembership';
  id: string;
  createdOnDate: string | null;
  renewedOnDate: string | null;
  expiresOnDate: string | null;
  membershipPhotoFileName: string | null;
} | null

I have tried going down one more level by using GetUserWithMembershipQuery['getUser']['memberships'], but I get an error saying that the 'Property memberships does not exist on type ...'

Is this because getUser or memberships is possibly null? Is there a way I can extract this type? Any help pointing to resources with how I can better understand this would be a great help.

Thank you.

Upvotes: 2

Views: 340

Answers (1)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249466

The problem is that under strictNullChecks if a type is in a union with null then no members will be accessible. This is the case both for value and type expressions. You can still get the type but you need to exclude null from the union using the Exclude conditional type. The syntax becomes a bit too convoluted to write in just one line so I broke it down in several steps :

type getUser = Exclude<GetUserWithMembershipsQuery['getUser'], null>
type memberships = Exclude<getUser['memberships'], null>
type items = Exclude<memberships['items'], null>
type item =  Exclude<items[number], null>

Upvotes: 3

Related Questions