Home > OS >  How can I correctly type `let skills` using this generated typescript code?
How can I correctly type `let skills` using this generated typescript code?

Time:01-11

I'm using typescript to describe a variable but I'm encountering a strange issue:

import type { PlayerByIdQuery } from "generated/queries";

let skills: PlayerByIdQuery["playerById"]["skills"];

The error is:

Property 'skills' does not exist on type '{ __typename?: "Player" | undefined; id: string; number: string; skills?: { ...; }[] | ... 1 more ....'.ts(2339)

The type is:

export type PlayerByIdQuery = {
  __typename?: "Query";
  playerById?: {
    __typename?: "Player";
    id: string;
    number: string;
    skills?: Array<{
      __typename?: "PlayerSkill";
      description: string;
      id: string;
      playerId: string;
    }> | null;
  } | null;
};

It works if I change the type to (note the both missing | null):

export type PlayerByIdQuery = {
  __typename?: "Query";
  playerById: {
    __typename?: "Player";
    id: string;
    number: string;
    skills?: Array<{
      __typename?: "PlayerSkill";
      description: string;
      id: string;
      playerId: string;
    }>;
  };
};

What am I doing wrong?

How can I correctly type let skills?

CodePudding user response:

The problem is that playerById is optional (may be undefined) or null.

And null['skills'] is not valid, which means that:

type A = { skills: string[] } | null
type B = A['skills'] // also not valid

So you need to explicitly remove the undefined and null from the type before you drill into it.

Luckily, typescript comes with a utility type for just that called NonNullable<T>.

type A = { skills: string[] } | null
type B = NonNullable<A>['skills'] // now works fine

So now just apply this to your own types like so:

let skills: NonNullable<PlayerByIdQuery["playerById"]>["skills"] = [
  {
    __typename: 'PlayerSkill',
    description: 'Fancy punch',
    id: 'abc123',
    playerId: 'def456'
  }
]

See playground

  • Related