DevBolt
Processed in your browser. Your data never leaves your device.

GraphQL Type System Explained

GraphQL has a rich type system that maps cleanly to TypeScript. Use the converter above to see how each GraphQL type translates to TypeScript interfaces, enums, and type aliases.

GraphQL to TypeScript Converter

Convert GraphQL SDL schemas to TypeScript interfaces, types, enums, and operations. Paste your schema and get typed code instantly.

// ── Scalars ──

export type DateTime = string;

// ── Enums ──

export enum UserRole {
  ADMIN = "ADMIN",
  EDITOR = "EDITOR",
  AUTHOR = "AUTHOR",
  READER = "READER",
}

// ── Types ──

/** A blog post */
export interface Post {
  id: string;
  title: string;
  content: string;
  slug: string;
  published: boolean;
  createdAt: string;
  updatedAt?: string;
  author: User;
  tags: Tag[];
  comments: Comment[];
}

export interface User {
  id: string;
  name: string;
  email: string;
  avatar?: string;
  bio?: string;
  posts: Post[];
  role: UserRole;
}

export interface Comment {
  id: string;
  body: string;
  author: User;
  post: Post;
  createdAt: string;
}

export interface Tag {
  id: string;
  name: string;
  slug: string;
  posts: Post[];
}

// ── Input Types ──

export interface CreatePostInput {
  title: string;
  content: string;
  slug?: string;
  published?: boolean;
  tagIds?: string[];
}

export interface UpdatePostInput {
  title?: string;
  content?: string;
  slug?: string;
  published?: boolean;
  tagIds?: string[];
}

// ── Operations ──

export interface Query {
  /** Args: (limit: number, offset: number, published: boolean) */
  posts: Post[];
  /** Args: (id: string) */
  post?: Post;
  users: User[];
  /** Args: (id: string) */
  user?: User;
  tags: Tag[];
}

export interface PostsArgs {
  limit?: number;
  offset?: number;
  published?: boolean;
}

export interface PostArgs {
  id: string;
}

export interface UserArgs {
  id: string;
}

export interface Mutation {
  /** Args: (input: CreatePostInput) */
  createPost: Post;
  /** Args: (id: string, input: UpdatePostInput) */
  updatePost?: Post;
  /** Args: (id: string) */
  deletePost: boolean;
  /** Args: (name: string, email: string, password: string) */
  register: User;
}

export interface CreatePostArgs {
  input: CreatePostInput;
}

export interface UpdatePostArgs {
  id: string;
  input: UpdatePostInput;
}

export interface DeletePostArgs {
  id: string;
}

export interface RegisterArgs {
  name: string;
  email: string;
  password: string;
}

4

Types

2

Inputs

1

Enums

0

Unions

0

Interfaces

1

Scalars

2

Operations

45

Fields

Press Ctrl+Enter to copy

Default Scalar Mappings

String string
Int number
Float number
Boolean boolean
ID string
DateTime string
Date string
Time string
JSON Record<string, unknown>
JSONObject Record<string, unknown>
Upload File
BigInt bigint

Object types

Object types are the most common. 'type User { id: ID!, name: String! }' becomes a TypeScript interface with the same fields. Non-null fields (!) become required properties, nullable fields become optional or have '| null'. Arrays like '[Post!]!' become 'Post[]'.

Input types

Input types define the shape of mutation arguments. 'input CreateUserInput { name: String!, email: String! }' generates a separate TypeScript interface. Inputs often have more optional fields than output types since you typically only send the fields you want to update.

Enums and unions

GraphQL enums like 'enum Status { ACTIVE, INACTIVE }' can become TypeScript enums or const objects (preferred for tree-shaking). Unions like 'union SearchResult = User | Post' become TypeScript union types: 'type SearchResult = User | Post'. Both preserve the type safety of the original schema.

Interfaces and scalars

GraphQL interfaces like 'interface Node { id: ID! }' become TypeScript interfaces that other types can extend. Custom scalars like 'scalar DateTime' need explicit TypeScript type mappings — DateTime typically maps to 'string', JSON to 'Record<string, unknown>', and Upload to 'File'.

Frequently Asked Questions

What is the difference between type and input in GraphQL?

'type' defines output shapes returned by queries/mutations. 'input' defines argument shapes sent by the client. They generate identical TypeScript interfaces but serve different purposes: types describe what the API returns, inputs describe what the client sends.

Should I use TypeScript enums or const objects for GraphQL enums?

Const objects (as const) are generally preferred because they tree-shake better, work with string comparisons, and don't generate runtime JavaScript enum objects. TypeScript enums are fine for smaller projects where tree-shaking isn't critical.

How do nullable and non-null types map to TypeScript?

In GraphQL, fields are nullable by default. 'name: String' means the value can be null. 'name: String!' means it's guaranteed non-null. In TypeScript, nullable fields can be represented as optional properties (name?: string) or explicit union types (name: string | null).

Related Convert Tools