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
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.
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
Tinstead ofT | nullwill workaround the existing behaviour - but note that it will effect your type-safety protection because if a field will benulland 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.