Search code examples
typescripttsconfig

Use of indexed access types yields error in strict mode


I use GraphQL Code Generator to generate types from my GraphQL queries. One of those types is the following:

type FindAllFilmsQuery = {
  __typename?: 'Root';
  allFilms?: {
    __typename?: 'FilmsConnection';
    films?: Array<{
      __typename?: 'Film';
      id: string;
      title?: string | null;
    } | null> | null;
  } | null;
};

Now I would like to use indexed access types to do the following:

let film: FindAllFilmsQuery['allFilms']['films'][0];

But this yields an error:

TS2339: Property 'films' does not exist on type '{ __typename?: "FilmsConnection" | undefined; films?: ({ __typename?: "Film" | undefined; id: string; title?: string | null | undefined; } | null)[] | null | undefined; } | null | undefined'.

If I set "strict": false in my TSConfig everything works fine - no error. However, I would like to keep strict to true. Is there any solution/recommendation to fix this problem?


Solution

  • Let's look at a much simpler case:

    type A = { foo?: { bar: string } }
    type B = A['foo']['bar']
    // Property 'bar' does not exist on type '{ bar: "baz"; } | undefined'.(2339)
    

    See the problem now?

    You can't index optional property like this because you can't index undefined with anything, and undefined is a possible value of an optional property.


    What you can do is remove all the nullish possible types with NonNullable<T>.

    type A = { foo?: { bar: string } }
    type B = NonNullable<A['foo']>['bar'] // fine
    

    However, your example is a few levels deep, so you may need to make things NonNullable multiple times.

    let film: NonNullable<
      NonNullable<
        FindAllFilmsQuery['allFilms']
      >['films']
    >[number]
    

    See Playground