Catch the highlights of GraphQLConf 2023! Click for recordings. Or check out our recap blog post.
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: { 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 {
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.