typescriptgraphqlcode-generationgraphql-codegen

Generate the correct type instead of a union in GraphQL codegen


I am trying to migrate a setup which generates all the types exactly like what the server has into something which is based on just the document nodes that we've written.

I currenly have this configuration in .graphqlrc.js

/** @type {import('graphql-config').IGraphQLConfig} */
const graphqlConfig = {
  schema: process.env.NEXT_PUBLIC_API_URL,
  documents: './src/graphql/**/*.ts',
  extensions: {
    codegen: {
      hooks: {
        afterAllFileWrite: ['prettier --write'],
      },
      generates: {
        './src/__generated__/graphql.ts': {
          plugins: [
            'typescript',
            'typescript-operations',
            {
              add: {
                content: '/* eslint-disable */',
              },
            },
          ],
          config: {
            disableDescriptions: true,
          },
        },
        './src/__generated__/introspection-result.ts': {
          plugins: ['fragment-matcher'],
          config: {
            useExplicitTyping: true,
          },
        },
      },
    },
  },
}

and this generates something like below

export type QueryName = {
  __typename?: 'Query'
  resource?:
    | { __typename?: 'A' }
    | { __typename?: 'B' }
    | {
        __typename?: 'C'
        id: string
        prop1: any
        prop2: any
      }
}

that is not exactly what I was expecting to be generated. I am expecting something like

export type QueryName = {
  __typename?: 'Query'
  resource?: {
        __typename?: 'C'
        id: string
        prop1: any
        prop2: any
  }
}

as I am only querying for C. The types that is currently getting generated will affect a lot of codes whereas if I could output what I want to achieve, we only need to change the types.

I've tried playing with the config found here but could not find a solution. Please let me know if this is possible or if there's something I could take a look at to solve this.

Thanks in advance!


Solution

  • I eventually end up using tiny-invariant package for this. Consider the ff code

    const {data} = useUserQuery({variables: {id}});
    
    // more codes here...
    
    invariant(data.user.__typename === "User");
    
    // now we should get the type that we want here