Graphql-code-generator: [Question]Avoid having to use no non null assertion everywhere with Gatsby

Created on 23 Jun 2019  路  4Comments  路  Source: dotansimha/graphql-code-generator

It is my first time using graphql-codegen in a project, thank you very much for providing this tool.


I am working on a starter for Gatsby with typescript, and I am using graphql-codegen to generate the types for gatsby's graphql server.

It works well but all the fields are of type Maybe<T>, I am not sure why, the data is there in the API and is not null.

So in my code I have to add a lot of non null assertion like this:

  const {
    canonicalUrl,
    companyName,
    siteTitle,
  } = layoutQuery.site!.siteMetadata!
  return (
    <>
      <Header siteTitle={siteTitle!} />
      <main>{children}</main>
      <footer>
        漏 {new Date().getFullYear()} Copyright{' '}
        <a href={canonicalUrl!}>{companyName}</a> - All rights reserved

I feel it is a dirty way to handle this problem and I wonder if you have an advice for improving my code.

Describe the solution you'd like

A solution that feels right.

Describe alternatives you've considered

I tried to make the checks manually like this:

const siteMetadata = layoutQuery.site && layoutQuery.site.siteMetadata
  const companyName = siteMetadata ? siteMetadata.companyName : ''
  const canonicalUrl = siteMetadata ? siteMetadata.canonicalUrl : ''
  const siteTitle = siteMetadata ? siteMetadata.siteTitle : ''
  return (
    <>
      <Header siteTitle={siteTitle || ''} />
      <main>{children}</main>
      <footer>
        漏 {new Date().getFullYear()} Copyright{' '}
        <a href={canonicalUrl || ''}>{companyName || ''}</a> - All rights
        reserved
      </footer>
    </>
  )

But I feel it is very verbose.

Additional context

Here is a link to this code in the repository:
https://github.com/abumalick/gatsby-typescript-material-rebass-starter/blob/master/src/components/Layout.tsx#L23-L34

And here is the generated types:
https://github.com/abumalick/gatsby-typescript-material-rebass-starter/blob/master/src/types/gatsbyGraphql.ts#L2162

My config:

overwrite: true
schema: 'http://localhost:8000/___graphql'
documents:
  - ./src/**/*.{ts,tsx}
  - ./node_modules/gatsby-*/**/*.js
generates:
  src/types/gatsbyGraphql.ts:
    plugins:
      - 'typescript'
      - 'typescript-operations'
    config:
      avoidOptionals: true

Most helpful comment

It's a matter of the way you consume the types. The default behaviour generates Maybe when you declare a nullable type in your schema. It's not our choice to generate it, it just generates the reflection of your schema.
But, we do want to allow maximum flexibility for developers, so using T instead of T | null will workaround the existing behaviour - but note that it will effect your type-safety protection because if a field will be null and you'll try to access it as object - you'll get a runtime error.

The correct way to workaround this is to change your schema and reflect the real status of your fields - if it's a value that should never be null - add ! to your schema definition.

All 4 comments

I just found another workaround that is a lot better for me:
Set maybeValue to T instead of T | null

I will close the issue as I have my answer.

Your advices are very welcome through. I wonder if there is a very good reason to not do this.

I was wondering the same thing. Probably should have left the issue open.

It's a matter of the way you consume the types. The default behaviour generates Maybe when you declare a nullable type in your schema. It's not our choice to generate it, it just generates the reflection of your schema.
But, we do want to allow maximum flexibility for developers, so using T instead of T | null will workaround the existing behaviour - but note that it will effect your type-safety protection because if a field will be null and you'll try to access it as object - you'll get a runtime error.

The correct way to workaround this is to change your schema and reflect the real status of your fields - if it's a value that should never be null - add ! to your schema definition.

The problem is that when Gatsby automatically infers the GraphQL schema from the data it receives, it tends to define all types very loosely without the !. I had to explicitly define the schema with non-nullable types in order to avoid using the maybeValue: T and non null assertion workarounds in typescript. It was a lot of work, but it makes for a much more robust generation of query types.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

NickClark picture NickClark  路  3Comments

mszczepanczyk picture mszczepanczyk  路  3Comments

edorivai picture edorivai  路  3Comments

dotansimha picture dotansimha  路  3Comments

leonardfactory picture leonardfactory  路  3Comments