GraphQL to TypeScript Generator & Codegen

GraphQL to TypeScript Generator & Codegen

Convert GraphQL schema SDL and queries into TypeScript types, interfaces, enums, and resolvers. Instant in-browser codegen with zero config or server upload.

Btn samples
Regime label
Lbl schema source
Lbl quick scalars
Production Ready Export
12Nodes
AST Architecture
Object: 6Interface: 1Enum: 1Input: 1
83%Strict
Nullability Guard

High non-null strictness (safe against unexpected runtime undefined).

Lbl status valid
/**
 * Strongly Typed GraphQL TypeScript Artifacts
 * Generated via ToolsAA In-Browser Codegen Engine [Regime: strict-modern]
 * 100% In-Browser AST synthesis - Zero server upload
 */

type Maybe<T> = T | null;

type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
type MakeOptional<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]?: Maybe<T[SubKey]> };
type MakeMaybe<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]: Maybe<T[SubKey]> };

/** All Built-In & Custom GraphQL Scalars */
type Scalars = {
  DateTime: string;
};

type Scalars = {
  JSON: Record<string, unknown>;
};

type Scalars = {
  Money: number;
};

type ProductStatus = 'DRAFT' | 'ACTIVE' | 'ARCHIVED' | 'OUT_OF_STOCK';

type Node = {
  __typename?: string;
  readonly id: string;
  readonly createdAt: string;
  readonly updatedAt: string;
};

type MoneyAmount = {
  __typename?: 'MoneyAmount';
  readonly amount: number;
  readonly currency: string;
};

type ProductVariant = {
  __typename?: 'ProductVariant';
  readonly id: string;
  readonly sku: string;
  readonly title: string;
  readonly price: MoneyAmount;
  readonly inStock: boolean;
  readonly inventoryQuantity: number;
  readonly createdAt: string;
  readonly updatedAt: string;
};

type Review = {
  __typename?: 'Review';
  readonly id: string;
  readonly author: string;
  readonly rating: number;
  readonly comment: Maybe<string>;
  readonly metadata: Maybe<Record<string, unknown>>;
  readonly createdAt: string;
  readonly updatedAt: string;
};

type Product = {
  __typename?: 'Product';
  readonly id: string;
  readonly title: string;
  readonly slug: string;
  readonly description: Maybe<string>;
  readonly status: ProductStatus;
  readonly price: MoneyAmount;
  readonly variants: ReadonlyArray<ProductVariant>;
  readonly reviews: ReadonlyArray<Review>;
  readonly createdAt: string;
  readonly updatedAt: string;
};

type Query = {
  __typename?: 'Query';
  readonly product: Maybe<Product>;
  readonly products: ReadonlyArray<Product>;
};

type Mutation = {
  __typename?: 'Mutation';
  readonly createProduct: Product;
  readonly deleteProduct: boolean;
};

type CreateProductInput = {
  readonly title: string;
  readonly slug: string;
  readonly description?: Maybe<string>;
  readonly price: number;
  readonly currency?: Maybe<String = "USD">;
  readonly status?: Maybe<ProductStatus = DRAFT>;
};
Lbl types count12
Lbl fields count40
Lbl enums count1
Lbl unions count0
Lbl scalars count3
Lbl execution time< 1ms
Technical Reference & Architecture Guide

GraphQL to TypeScript Generator & Codegen Guide

Convert GraphQL schema SDL and queries into TypeScript types, interfaces, enums, and resolvers. Instant in-browser codegen with zero config or server upload.

GraphQL to TypeScript Generator & Codegen Guide — Client-Side In-Memory Architecture & Data Flow
GraphQL to TypeScript Generator & Codegen Guide — Client-Side In-Memory Architecture & Data Flow

Key Parameters & Controls

GraphQL Schema Source (SDL vs Introspection JSON)Schema Definition Document (AST Input)

Standard GraphQL Schema Definition Language (SDL) text or JSON-serialized Introspection response (__schema root object). Conforms to the official GraphQL October 2021 specification grammar.

Default: Schema Definition Language (SDL)
Nullability & Optionality StrategyCompiler Nullability Mode (Enum)

Maps GraphQL non-null (!) vs nullable fields to TypeScript type expressions. Controls whether nullable fields generate 'T | null', 'Maybe<T>', or optional properties 'field?: T' under TypeScript strictNullChecks.

Default: Maybe<T> = T | null | undefined
Type Declaration ParadigmType Emission Syntax (Enum)

Specifies whether GraphQL Object types compile to TypeScript 'type' aliases or 'interface' declarations. Type aliases support indexed access and unions; interfaces allow declaration merging in extensible SDKs.

Default: type (Type Aliases)
Enum Compilation FormatEnum Representation (Enum)

Controls whether GraphQL enums compile to TypeScript native 'enum' runtime objects or tree-shakable string literal unions ('ADMIN' | 'USER') with companion const dictionaries.

Default: String Literal Union
Custom Scalar Type Mapping (ScalarMappingDictionary)Dictionary (Record<string, string>)

Resolves user-defined GraphQL scalars to concrete TypeScript types. Default maps: ID to 'string', Int to 'number', Float to 'number', String to 'string', Boolean to 'boolean', DateTime to 'string | Date'.

Default: DateTime: string, JSON: Record<string, unknown>
Immutable / Readonly Array ModifierImmutability Flag (Boolean)

When enabled, injects the 'readonly' modifier into every object field and wraps all list types into 'ReadonlyArray<T>', enforcing compile-time immutability in Redux and Zustand state stores.

Default: true

Pro Tips & Best Practices

Universal Nullability Pitfall: GraphQL Nullable Fields vs TypeScript Undefined

In GraphQL, a nullable output field without exclamation mark returns explicit null when unpopulated, not undefined. In TypeScript, declaring 'field?: string' permits undefined but rejects explicit null under strictNullChecks. For client response types, always generate 'field: Maybe<string>' (string | null) rather than 'field?: string' to prevent runtime TypeError exceptions when accessing server payloads containing null values.

Avoid Native Numeric Enums: Use String Literal Unions for Zero-Runtime Bundles

TypeScript native 'enum' generates a two-way lookup JavaScript IIFE runtime object that cannot be tree-shaken by modern bundlers (Vite, Rollup, esbuild). In client applications, generating 'type UserRole = "ADMIN" | "MEMBER"' combined with an 'as const' freeze array eliminates 100% of runtime bundle overhead while providing identical autocomplete and stricter type narrowing.

Fragment Masking with TypedDocumentNode Over Generic Query Wrappers

Instead of emitting monolithic query result types and manually casting fetch responses, generate TypedDocumentNode<ResultType, VariablesType> instances. Modern GraphQL clients (Apollo Client 3.7+, urql, and graphql-request) automatically infer both the query data shape and required variables directly from the document node without explicit type parameters.

Distinguish Serialization Wire Types from In-Memory Domain Models

Custom scalars such as DateTime, JSON, and BigInt travel across the network as JSON strings or raw numbers. If your codegen maps 'DateTime' to JavaScript 'Date', fetching with standard JSON.parse() will leave the field as a string, causing runtime date method failures (e.g., date.toISOString() is not a function). Use 'string' for wire response types and reserve 'Date' for parsed domain models or deserialization transformers.

Common Gotchas & Troubleshooting

⚠️TypeScript Compiler Error TS2322: Type 'null' is not assignable to type 'undefined' on generated input objects

GraphQL input objects treat omitted fields as undefined, whereas explicit null signifies intentional clearing. Enable exactOptionalPropertyTypes in tsconfig.json and configure the codegen input strategy to emit 'field?: string | null' for input arguments, distinguishing between omitting a key and passing an explicit null payload.

⚠️Circular reference depth exceeds TypeScript compiler limits in deeply nested recursive schemas

Self-referencing schema structures (such as Comment -> replies: [Comment!]! or Category -> children: [Category!]!) can trigger TS2589 infinite type instantiation. Resolve this by emitting type definitions as 'interface' declarations rather than nested recursive 'type' aliases, which leverages TypeScript's lazy interface property resolution.

⚠️Syntax Error: Unexpected token in JSON at position 0 when pasting Introspection results

Ensure you paste the entire JSON payload containing the '__schema' or 'data.__schema' root key. If the introspection query was extracted via curl or Postman, strip HTTP response wrapper headers or unescape escaped string quotes before parsing.

⚠️Apollo Federation directives (@key, @external, @shareable) cause unknown directive parse failures

The standard GraphQL specification parser does not bundle Apollo Federation v1/v2 schema directives by default. The generator includes built-in federation directive stubs; ensure the 'Enable Federation Directives' toggle is active or paste the standard Federation directive definition block at the top of your SDL.

Frequently Asked Questions

How does GraphQL nullability map to TypeScript optional fields vs null unions?▼

In GraphQL SDL, fields are nullable by default and only non-null when marked with an exclamation point (!). In TypeScript with strictNullChecks, non-null fields (String!) compile to 'string', while nullable fields (String) compile to 'string | null' (or 'Maybe<string>'). For input objects, nullable fields become optional properties ('field?: string | null') because GraphQL permits omitting arguments in queries and mutations.

Should GraphQL enums be converted to TypeScript enum or string literal union types?▼

String literal unions ('type Status = "ACTIVE" | "INACTIVE"') are recommended for modern web applications because they compile to zero JavaScript runtime code, tree-shake perfectly, and accept plain string literals without requiring enum imports. Native TypeScript enums ('enum Status { Active = "ACTIVE" }') should only be chosen when runtime object reflection, reverse lookup, or legacy library integration is required.

What is the difference between Schema Types codegen and Client Operation Types codegen?▼

Schema Types codegen compiles the entire GraphQL backend schema (every type, input, enum, and resolver signature) into comprehensive TypeScript interfaces. Client Operation Types codegen inspects specific client query documents, selects only the queried sub-fields (applying selection sets and fragments), and generates unnested, precise response types matching the exact JSON payload returned by that specific query.

Why does the GraphQL ID scalar serialize to string or number instead of a dedicated type in TypeScript?▼

The official GraphQL specification defines the ID scalar as a unique identifier serialized as a String, but permits clients to pass either string or integer values as input. Consequently, TypeScript codegen maps ID to 'string' (for output types) or 'string | number' (for input arguments). Applications requiring type safety between different entity IDs should use branded nominal types (e.g., 'type UserId = string & { readonly __brand: unique symbol }').

Related Tools & Utilities

All Tools →