Search code examples
typescriptgraphql-codegen

TypeScript incorrectly errors when I map and flat an array?


I'm using GraphQL Codegen to generate TypeScript types from my GraphQL schema. Here is my query, I've used a fragment so that it has it's only type which is easy to export:

query reservationsPage($schoolSettingId: Int!, $day: UnixDate!) {
  roomsForSchoolSettingAll(schoolSettingId: $schoolSettingId) {
    ...reservationsPage
  }
}

fragment reservationsPage on Room {
    id
    name
    children {
      id
      name
      registrationToday(day: $day) {
        id
        checkIn
        checkOut
        importantInformation
        plannedCheckOut
        absent
        pickUpBy {
          id
          name
        }
      }
    }
}

The data returned looks something like this:

const res = [
  {
    id: 1,
    __typename: "Room",
    name: 'Name 1',
    children: []
  },
  {
    id: 2,
    __typename: "Room",
    name: 'Name 2',
    children: [
      {
        id: 3,
        __typename: "ChildProfile",
        name: 'James',
        registration: [
          {
            id: 4,
            __typename: "Registration",
            checkIn: "06:00:00",
            checkOut: "14:00:00",
            absent: null,
            importantInformation: null,
            pickUpBy: null
            plannedCheckOut: null  
          }
        ]
      }
    ]
  }
]

I can use this type on a new variable and it works as expected:

const childrenCurrent: ReservationsPageFragment['children'] = roomsForSchoolSettingAll.find(
    (room) => room.id === selectedRoomId,
  )?.children;

However when I try and use it on anouther variable I get a TypeScript error:

const childrenAll: ReservationsPageFragment['children'] = roomsForSchoolSettingAll
  .map((room) => room.children)
  .flat();

TS2322: Type '(({ __typename?: "ChildProfile" | undefined; } & Pick<ChildProfile, "id" | "name"> & { registrationToday?: ({ __typename?: "Registration" | undefined; } & Pick<...> & { ...; }) | null | undefined; }) | null | undefined)[]' is not assignable to type 'Maybe<{ __typename?: "ChildProfile" | undefined; } & Pick<ChildProfile, "id" | "name"> & { registrationToday?: ({ __typename?: "Registration" | undefined; } & Pick<...> & { ...; }) | null | undefined; }>[]'.   Type '({ __typename?: "ChildProfile" | undefined; } & Pick<ChildProfile, "id" | "name"> & { registrationToday?: ({ __typename?: "Registration" | undefined; } & Pick<...> & { ...; }) | null | undefined; }) | null | undefined' is not assignable to type 'Maybe<{ __typename?: "ChildProfile" | undefined; } & Pick<ChildProfile, "id" | "name"> & { registrationToday?: ({ __typename?: "Registration" | undefined; } & Pick<...> & { ...; }) | null | undefined; }>'.     Type 'undefined' is not assignable to type 'Maybe<{ __typename?: "ChildProfile" | undefined; } & Pick<ChildProfile, "id" | "name"> & { registrationToday?: ({ __typename?: "Registration" | undefined; } & Pick<...> & { ...; }) | null | undefined; }>'.


Solution

  • If you do a substitution in the error message text, it becomes more readable:

    TS2322:
    Type '((X) | null | undefined)[]' is not assignable to type 'Maybe<X>[]'.
    Type '(X) | null | undefined' is not assignable to type 'Maybe<X>'.
    Type 'undefined' is not assignable to type 'Maybe<X>'.

    where the X stands for

    { __typename?: "ChildProfile" | undefined; } & Pick<ChildProfile, "id" | "name"> & { registrationToday?: ({ __typename?: "Registration" | undefined; } & Pick<...> & { ...; }) | null | undefined; }

    Now we can see that the compiler indicates that the type Maybe<X> cannot hold a value undefined.
    To satisfy the compiler, you have multiple options

    • filter out undefined values
    • use a typecast (as mentioned in Daniele Ricci's answer)
    • change the definition of the Maybe type to allow undefined values

    If you choose to modify the Maybe type, there is an example how to do that in the GraphQL code generator documentation:

    enter image description here