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:

scalar Date
schema {
  query: Query
type Query {
  me: User!
  user(id: ID!): User
  allUsers: [User]
  search(term: String!): [SearchResult!]!
  myChats: [Chat!]!
enum Role {
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:

query findUser($userId: ID!) {
  user(id: $userId) {
fragment UserFields on User {

And with the following codegen.ts configuration file:

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: string;
  String: string;
  Boolean: boolean;
  Int: number;
  Float: number;
  Date: 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'];
export type QuerySearchArgs = {
  term: Scalars['String'];
export enum Role {
  User = 'USER',
  Admin = 'ADMIN'
export type Node = {
  id: Scalars['ID'];
export type SearchResult = User | Chat | ChatMessage;
export type User = Node & {
  __typename?: 'User';
  id: Scalars['ID'];
  username: Scalars['String'];
  email: Scalars['String'];
  role: Role;
export type Chat = Node & {
  __typename?: 'Chat';
  id: Scalars['ID'];
  users: Array<User>;
  messages: Array<ChatMessage>;
export type ChatMessage = Node & {
  __typename?: 'ChatMessage';
  id: Scalars['ID'];
  content: Scalars['String'];
  time: Scalars['Date'];
  user: User;
export type FindUserQueryVariables = Exact<{
  userId: Scalars['ID'];
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 {
export const FindUserDocument = `
    query findUser($userId: ID!) {
  user(id: $userId) {
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),

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