Catch the highlights of GraphQLConf 2023! Click for recordings. Or check out our recap blog post.
Docs
Advanced Usage
How does it work?

How does GraphQL Code Generator Work?

In order to generate code and types, GraphQL Code Generator relies on 2 main core concepts of GraphQL:

  • GraphQL Introspection allows fetching the types defined in the target GraphQL API
  • GraphQL AST allows to navigate through both client-side operations and remote schema types

Once all GraphQL types (schema types and operations) are identified, GraphQL Code Generator relies on a set of plugins to generate specific code snippets and types.

This process, applied to the @graphql-codegen/typescript plugin, is illustrated below:

Codegen flow example

💡

Operations and fragments must have unique names

GraphQL Code Generator checks for this automatically and will let you know if you have any conflicts.

Example with @graphql-codegen/typescript

Given the following GraphQL schema:

schema.graphql
scalar Date
 
schema {
  query: Query
}
 
type Query {
  me: User!
  user(id: ID!): User
  allUsers: [User]
  search(term: String!): [SearchResult!]!
  myChats: [Chat!]!
}
 
enum Role {
  USER
  ADMIN
}
 
interface Node {
  id: ID!
}
 
union SearchResult = User | Chat | ChatMessage
 
type User implements Node {
  id: ID!
  username: String!
  email: String!
  role: Role!
}
 
type Chat implements Node {
  id: ID!
  users: [User!]!
  messages: [ChatMessage!]!
}
 
type ChatMessage implements Node {
  id: ID!
  content: String!
  time: Date!
  user: User!
}

And the following operation (Query) on client-side:

operation.graphql
query findUser($userId: ID!) {
  user(id: $userId) {
    ...UserFields
  }
}
 
fragment UserFields on User {
  id
  username
  role
}

And with the following codegen.ts configuration file:

codegen.ts
import { CodegenConfig } from '@graphql-codegen/cli';
 
const config: CodegenConfig = {
  schema: 'http://localhost:3333',
  generates: {
    'types-and-hooks.tsx': { plugins: ['typescript', 'typescript-operations', 'typescript-react-query'] },
  },
};
export default config;

@graphql-codegen/typescript plugin can generate the following TypeScript typings and React hooks files based on defined operations:

// …
 
/** All built-in and custom scalars, mapped to their actual values */
export type Scalars = {
  ID: { input: string; output: string; };
  String: { input: string; output: string; };
  Boolean: { input: boolean; output: boolean; };
  Int: { input: number; output: number; };
  Float: { input: number; output: number; };
  Date: { input: any; output: any; };
};
 
export type Query = {
  __typename?: 'Query';
  me: User;
  user?: Maybe<User>;
  allUsers?: Maybe<Array<Maybe<User>>>;
  search: Array<SearchResult>;
  myChats: Array<Chat>;
};
 
 
export type QueryUserArgs = {
  id: Scalars['ID']['input'];
};
 
 
export type QuerySearchArgs = {
  term: Scalars['String']['input'];
};
 
export enum Role {
  User = 'USER',
  Admin = 'ADMIN'
}
 
export type Node = {
  id: Scalars['ID']['output'];
};
 
export type SearchResult = User | Chat | ChatMessage;
 
export type User = Node & {
  __typename?: 'User';
  id: Scalars['ID']['output'];
  username: Scalars['String']['output'];
  email: Scalars['String']['output'];
  role: Role;
};
 
export type Chat = Node & {
  __typename?: 'Chat';
  id: Scalars['ID']['output'];
  users: Array<User>;
  messages: Array<ChatMessage>;
};
 
export type ChatMessage = Node & {
  __typename?: 'ChatMessage';
  id: Scalars['ID']['output'];
  content: Scalars['String']['output'];
  time: Scalars['Date']['output'];
  user: User;
};
 
export type FindUserQueryVariables = Exact<{
  userId: Scalars['ID']['input'];
}>;
 
 
export type FindUserQuery = { __typename?: 'Query', user?: { __typename?: 'User', id: string, username: string, role: Role } | null | undefined };
 
export type UserFieldsFragment = { __typename?: 'User', id: string, username: string, role: Role };
 
export const UserFieldsFragmentDoc = `
    fragment UserFields on User {
  id
  username
  role
}
    `;
export const FindUserDocument = `
    query findUser($userId: ID!) {
  user(id: $userId) {
    ...UserFields
  }
}
    ${UserFieldsFragmentDoc}`;
export const useFindUserQuery = <
      TData = FindUserQuery,
      TError = unknown
    >(
      dataSource: { endpoint: string, fetchParams?: RequestInit },
      variables: FindUserQueryVariables,
      options?: UseQueryOptions<FindUserQuery, TError, TData>
    ) =>
    useQuery<FindUserQuery, TError, TData>(
      ['findUser', variables],
      fetcher<FindUserQuery, FindUserQueryVariables>(dataSource.endpoint, dataSource.fetchParams || {}, FindUserDocument, variables),
      options
    );

Now our React components can use the type-safe useFindUserQuery() hook to query the GraphQL API.