TypeScript incorrectly errors when I map and flat an array?
Asked Answered
S

2

5

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; }>'.

Snelling answered 20/11, 2020 at 16:33 Comment(0)
T
9

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

Toole answered 23/11, 2020 at 9:19 Comment(0)
D
2

Sorry but from your question I can't understand if you are looking for an explanation of the cause of the error or just a way to make it works.

In the first case, I'm not a GraphQL master, so you can ignore my answer an looking for an answer from somebody who know GraphQL.

In the second case you could try not specifying the childrenAll type:

const childrenAll = roomsForSchoolSettingAll
  .map((room) => room.children)
  .flat();

or using type cast:

const childrenAll: ReservationsPageFragment['children'] = roomsForSchoolSettingAll
  .map((room) => room.children)
  .flat() as unknown as ReservationsPageFragment['children'];
Dentilingual answered 23/11, 2020 at 8:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.