Gatsby: Automatic TypeScript Definitions Generation

Created on 20 May 2019  Β·  28Comments  Β·  Source: gatsbyjs/gatsby

Summary

This feature request stems from a conversation on the Gatsby discord server that I had with @DSchau in which I asked:

Is there any way to generate TypeScript definitions for the results of each graphql'' query? This would allow us to ensure that all cases are covered, with regards to nullables, etc.

I did think that I might be able to use something like: npx [email protected] client:codegen --endpoint=http://localhost:8000/___graphql --target=typescript however, we use gatsby-image and it complains mightily about Unknown fragment "GatsbyContentfulFluid_withWebp" etc...

It just seems that this is something that Gatsby has the potential to do entirely for you on initial build, and then on each file change... Something to consider?

dschau: @StarvingDragon we've talked about generating the SDL (e.g. a snapshot of the current schema as apollo-like types) but hadn't considered Typescript definitions! Could you perhaps share some more info and/or open an issue with more detail for what you'd like?

Basic example & Motivation

So the benefit of this (auto-generated types) would be that if you're developing in TS, you could type all data passed into the pages/component as props mega simply! And you could also guarantee that after each rebuild, if the types changed, you'd know and have failing TS errors...

eg. imagine changing a field (say "author") in Contentful from required to optional. The next time that Gatsby would start up, it would know that field is now optional and update the TS definition such that author: Author | null. Leading anywhere that you're not handling a null value to throw TS errors.

Progress so far

I have managed to get the apollo:codegen tool to recognise the queries Gatsby uses by changing imports to import { graphql as gql } from 'gatsby', as I believe it's looking for gql tags. However, as stated above, it struggles with the Gatsby Image fragments, as it doesn't know what they are!

Most helpful comment

You should try using graphQL-codegen . They have documentation on using it with Gatsby.

npm i @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations --save-dev

There is currently an issue with their suggested config, so use the below config.

# codegen.yml
schema: http://localhost:8000/___graphql
documents:
  - ./src/**/*.{ts,tsx}
  - ./node_modules/gatsby-*/**/*.js
config:
  namingConvention:
    enumValues: keep
generates:
  ./src/graphqlTypes.ts:
    plugins:
      - typescript
      - typescript-operations

All 28 comments

CC: @pieh I recall you having something similar to this if I am not mistaken

@Siyfion I'm not sure if this still works - but you can try checking https://github.com/pieh/gatsby-query-result-type-gen

Yep, it doesn't work anymore after some refactoring done in gatsby (as I was importing some gatsby internals there), but it probably can be updated to work again.

The fragment blocker you mentioned - please check my code - I was importing "queries" directly from gatsby redux store (and not parsing your project directly). This ensures that any fragments that were used will be attached to queries (i.e. gatsby-image` fragments)

Ah nice @pieh! Is this something that the Gatsby team would consider incorporating as an official tool in future? I really think it'd be hugely useful!

I believe that the major breaking change seems to be this refactor: https://github.com/gatsbyjs/gatsby/commit/bbb8c36f78af806f6e79310bca9b3c99df107436 with maybe an element of https://github.com/gatsbyjs/gatsby/commit/3ca49f2635caa17ecfca83ac453a969c1d6aa68d thrown in for good measure too!

Ah nice @pieh! Is this something that the Gatsby team would consider incorporating as an official tool in future? I really think it'd be hugely useful!

This was one of my "weekend projects", and I don't think we really talked about it yet.

Now I start to remember more when I was working on this (why I didn't make it a plugin and made "standalone" tool). apollo-codegen used different version of graphql package and this was causing issues (when you have multiple versions of graphql package in node_modules it can cause weird issues ( for example errors like https://github.com/graphile/postgraphile/issues/677 ) - which also make it hard to incorporate this nicely

apollo-codegen used different version of graphql package and this was causing issues (when you have multiple versions of graphql package in node_modules it can cause weird issues

Yup, I've been on the receiving end of lots of those issues at various points over the last few months! It does seem to be a constant issue with the Apollo CLI unfortunately. Still, if Gatsby did support this tool as an official way to generate TypeScript Definitions, I'm sure there would be a fair amount of support for it ;)

You should try using graphQL-codegen . They have documentation on using it with Gatsby.

npm i @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations --save-dev

There is currently an issue with their suggested config, so use the below config.

# codegen.yml
schema: http://localhost:8000/___graphql
documents:
  - ./src/**/*.{ts,tsx}
  - ./node_modules/gatsby-*/**/*.js
config:
  namingConvention:
    enumValues: keep
generates:
  ./src/graphqlTypes.ts:
    plugins:
      - typescript
      - typescript-operations

Ooooh, that's interesting! Using programmatic API ( https://graphql-code-generator.com/docs/getting-started/#using-in-runtime ) this could really be turned into gatsby plugin I think

Wow, that's really cool @andykenward, though it still seems to struggle with the image fragments, eg:

$ graphql-codegen
  βœ” Parse configuration
  ❯ Generate outputs
    ❯ Generate ./src/graphqlTypes.ts
      βœ” Load GraphQL schemas
      βœ” Load GraphQL documents
      βœ– Generate
        β†’         at ./node_modules/gatsby-transformer-sharp/src/fragments.js:200:53


 Found 1 error

  βœ– ./src/graphqlTypes.ts
    AggregateError:
        GraphQLDocumentError: Unknown type "ImageSharpFixed".
            at ./node_modules/gatsby-transformer-sharp/src/fragments.js:1:35

Perhaps using their programmatic API we could add these "known" fragments in @pieh?

@Siyfion is works with GatsbyImageSharpFixed fragment.

I've made a Gatsby Starter you can try it out "Gatsby's default starter - TypeScript" with graphql-code-generator setup.

@andykenward we're using GatsbyContentfulFluid_withWebp and GatsbyContentfulFixed_withWebp throughout our code, so I can only assume that the issue relates to their usage as, like you say, your repo with images seems to work fine!

@Siyfion I think that's to do with not being able to query the Contentful GraphQL endpoint to generate their fragments. Adding the Gatsby Plugin gatsby-source-contentful and having valid api keys setup. When I try to generate the typings I get an error on any fragment referring to their fragments ContentfulFixed.

at ./node_modules/gatsby-source-contentful/src/fragments.js
 AggregateError:
        GraphQLDocumentError: Unknown type "ContentfulFixed".
            at ./node_modules/gatsby-source-contentful/src/fragments.js:1:35
        GraphQLDocumentError: Unknown type "ContentfulFixed".
            at ./node_modules/gatsby-source-contentful/src/fragments.js:9:45

Yeah @andykenward, it's weird because they are all there in that ./node_modules/gatsby-source-contentful/src/fragments.js file... Not really sure what's going on πŸ˜•

Edit: Ah.. I see they are all fragments on things like ContentfulFixed which ofc are exposed by the Contentful API, which it doesn't seem to be able to read.

@Siyfion Setting up Gatsby-source-graphql and configuring GraphCMS and GitHub GraphQL Endpoints lets me generate their schemas typings just using http://localhost:8000/___graphql as the one endpoint for "GraphQL code generator".

Perhaps using gatsby-source-graphql and configuring a Contentful GraphQL endpoint will solve it?

@andykenward but the thing is, I don't _think_ that the gatsby-source-contentful plugin is actually using Contentful's GraphQL API, as it's currently reserved for specific high-throughput/perf. spaces.

So the GraphQL fragments, types, etc. must _all_ be coming from the Gatsby plugin!?

EDIT: Seems to be generated by extend-node-type.js:508:

const fixedNode = fixedNodeType({ name: `ContentfulFixed`, getTracedSVG })

Hiya!

This issue has gone quiet. Spooky quiet. πŸ‘»

We get a lot of issues, so we currently close issues after 30 days of inactivity. It’s been at least 20 days since the last update here.

If we missed this issue or if you want to keep it open, please reply here. You can also add the label "not stale" to keep this issue open!

As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request. Check out gatsby.dev/contribute for more information about opening PRs, triaging issues, and contributing!

Thanks for being a part of the Gatsby community! πŸ’ͺπŸ’œ

I've been having a lot of success with graphql-codegen in many other projects, but unfortunately the moment I use a fluid/fixed image the whole thing comes crumbling down with a Gatsby project. Which is a shame! Why aren't the fragments exposed in the introspection query I wonder? @KyleAMathews

@Siyfion it's tricky as graphiql and other tools don't support it. @pieh has some initial work in that direction so hopefully we'll get there.

hey folks, run into this issue by chance -- I recently wrote a typescript plugin that does codegen automatically, using graphql-codegen api like pieh mentioned above. I've been using it for awhile, so far so good.

The codegen part can be its own plugin really -- I wanted to spin it out but haven't got the chance to do so yet. Give it a try if you're interested!

The new GraphiQL 1.0 re-design work should allow plugins which I think would support adding the extra fragments

@Siyfion about Fragments, I just copy-pasted them into the project from the plugin itself and got everything generated.
Just copy-paste this file.
https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-transformer-sharp/src/fragments.js
And you're good to go with graphql-codegen

If anyone wondering what is my config. Here it is.

overwrite: true
schema: "${SCHEMA:schema.graphql}"
pluckConfig:
  globalIdentifier: "graphql"
documents:
  - "./{src,gatsby-scripts}/**/*.graphql"
  - "./{src,gatsby-scripts}/**/*!(.generated).{ts,tsx}"
generates:
  src/types.generated.ts:
    plugins:
      - "typescript"
    config:
      namingConvention:
        enumValues: keep
  src/:
    preset: near-operation-file
    presetConfig:
      extension: .generated.ts
      baseTypesPath: ./types.generated.ts
    plugins:
      - typescript-operations
  ./schema.graphql:
    plugins:
      - "schema-ast"

Although I must admit strictness of types that are generated needs to be fixed because typings that are getting generated are way too "nullable" causing millions of null checks for no reason..
Please, continue the discussion about it here https://github.com/gatsbyjs/gatsby/issues/16310 anyone who is interested.

hey, has anybody encountered incompatible types between the gatsby image fluid fragments (generated by graphql-codegen) and the gatsby-image fluid prop? => https://github.com/gatsbyjs/gatsby/issues/17003

Hey,
I've created a plugin for handling TypeScript/Flow generation with apollo-codegen and configure the vscode apollographql plugin for autocomplete.

npm install --save gatsby-plugin-codegen

I would love to hear your feedback.

For people using Gatsby with Contentful, the problem is that Contentful, everything (Required or not) has | null after it, and none of the generated interfaces match the expected props. This is primarily because Contentful does not set non_null for Required fields, as explained here:

image

Right now I'm having to hard-code non-null types, so not getting the expected benefits of a code generator. Hope that we get a plugin or fundamental improvement from Contentful to improve this situation with nullability.

So what is the status of that and what is the state of the art way to integrate gatsby, graphQL, image fragments and typescript?
I currently have ts-graphql-plugin in my tsconfig.json, gatsby-plugin-typegen to generate types and schema, JS GraphQL plugin for WebStorm and gatsby-plugin-typescript, and it fails on the fragment. Is there a simple way to have it all running together?

Let's track this in the meta issue: https://github.com/gatsbyjs/gatsby/issues/17934
Please add your comments there, thanks!

Was this page helpful?
0 / 5 - 0 ratings