Skip to Content
SchemaInput Types

Input Types

TypeScript types with Input suffix are treated as GraphQL input types.

Basic Usage

/** Input for creating a new user */ export interface CreateUserInput { name: string; email: string | null; }

Generates:

"""Input for creating a new user""" input CreateUserInput { name: String! email: String }

Inline Objects

Input types can use inline object literals for nested structures. gqlkit automatically generates Input Object types with the naming convention {ParentTypeNameWithoutInputSuffix}{PascalCaseFieldName}Input:

import type { GqlField, Int } from "@gqlkit-ts/runtime"; export type CreateUserInput = { name: string; /** Profile information */ profile: { bio: string | null; /** User's age with default value */ age: GqlField<Int | null, { defaultValue: 18 }>; }; };

Generates:

input CreateUserInput { name: String! """Profile information""" profile: CreateUserProfileInput! } input CreateUserProfileInput { """User's age with default value""" age: Int = 18 bio: String }

Nested inline objects generate types with concatenated names (e.g., UserProfileInput.addressUserProfileAddressInput).

Similarly, inline string literal unions and external TypeScript enums are automatically converted to GraphQL enum types. See Inline Enums for details.

@oneOf Input Objects

Union types with Input suffix using inline object literals generate @oneOf input objects. Each union member must be an inline object literal with exactly one property. Property values can be scalar types, enum types, or references to Input Object types:

/** * Specifies how to identify a product. * Exactly one field must be provided. */ export type ProductInput = | { id: string } | { name: string } | { location: LocationInput };

Generates:

""" Specifies how to identify a product. Exactly one field must be provided. """ input ProductInput @oneOf { id: String location: LocationInput name: String }

Each property becomes a nullable field in the generated input type. The @oneOf directive ensures exactly one field is provided at runtime.

Inline @oneOf in Input Fields

Union types can be used as field types within Input Objects to create nested @oneOf input objects. The generated type name follows the convention {ParentTypeNameWithoutInputSuffix}{PascalCaseFieldName}Input:

export type CreateUserInput = { name: string; /** * User identifier - either by ID or email */ identifier: { id: string } | { email: string }; };

Generates:

input CreateUserInput { name: String! """User identifier - either by ID or email""" identifier: CreateUserIdentifierInput! } input CreateUserIdentifierInput @oneOf { email: String id: String }

Inline @oneOf in Resolver Arguments

Inline unions in resolver arguments are also converted to @oneOf input objects:

Query/Mutation arguments - naming convention: {PascalCaseResolverName}{PascalCaseArgPath}Input

export const findUser = defineQuery< { criteria: { identifier: { id: string } | { email: string }; }; }, User | null >(...);

Generates:

input FindUserCriteriaIdentifierInput @oneOf { email: String id: String } input FindUserCriteriaInput { identifier: FindUserCriteriaIdentifierInput! } type Query { findUser(criteria: FindUserCriteriaInput!): User }

Field resolver arguments - naming convention: {ParentTypeName}{PascalCaseFieldName}{PascalCaseArgPath}Input

export const posts = defineField< User, { filter: { status: string } | { createdAfter: string } | null; }, Post[] >(...);

Generates:

input UserPostsFilterInput @oneOf { createdAfter: String status: String } type User { posts(filter: UserPostsFilterInput): [Post!]! }

Default Values

Specify default values for Input Object fields using GqlField with the defaultValue option.

Basic Default Values

import { type GqlField, type Int } from "@gqlkit-ts/runtime"; export type PaginationInput = { limit: GqlField<Int, { defaultValue: 10 }>; offset: GqlField<Int, { defaultValue: 0 }>; includeArchived: GqlField<boolean, { defaultValue: false }>; }; export type SearchInput = { query: string; caseSensitive: GqlField<boolean, { defaultValue: true }>; maxResults: GqlField<Int | null, { defaultValue: null }>; }; export type GreetingInput = { name: GqlField<string, { defaultValue: "World" }>; prefix: GqlField<string, { defaultValue: "Hello" }>; };

Generates:

input PaginationInput { limit: Int! = 10 offset: Int! = 0 includeArchived: Boolean! = false } input SearchInput { query: String! caseSensitive: Boolean! = true maxResults: Int = null } input GreetingInput { name: String! = "World" prefix: String! = "Hello" }

Complex Default Values

Default values support arrays, objects, and enum values:

export type Status = "ACTIVE" | "INACTIVE" | "PENDING"; export type Priority = "LOW" | "MEDIUM" | "HIGH"; export type NestedConfig = { enabled: boolean; value: Int; }; export type FilterInput = { status: GqlField<Status, { defaultValue: "ACTIVE" }>; priorities: GqlField<Priority[], { defaultValue: ["MEDIUM", "HIGH"] }>; tags: GqlField<string[], { defaultValue: ["default"] }>; }; export type SettingsInput = { config: GqlField<NestedConfig, { defaultValue: { enabled: true; value: 100 } }>; limits: GqlField<Int[], { defaultValue: [10, 20, 30] }>; };

Generates:

input FilterInput { status: Status! = ACTIVE priorities: [Priority!]! = [MEDIUM, HIGH] tags: [String!]! = ["default"] } input SettingsInput { config: NestedConfig! = {enabled: true, value: 100} limits: [Int!]! = [10, 20, 30] }

Default Values with Directives

You can combine defaultValue with directives:

import { type GqlField, type GqlDirective, type Int } from "@gqlkit-ts/runtime"; export type LengthDirective<TArgs extends { min: number; max: number }> = GqlDirective<"length", TArgs, "INPUT_FIELD_DEFINITION" | "ARGUMENT_DEFINITION">; export type RangeDirective<TArgs extends { min: number; max: number }> = GqlDirective<"range", TArgs, "INPUT_FIELD_DEFINITION" | "ARGUMENT_DEFINITION">; export type CreateUserInput = { name: GqlField<string, { defaultValue: "Anonymous"; directives: [LengthDirective<{ min: 1; max: 100 }>]; }>; age: GqlField<Int, { defaultValue: 18; directives: [RangeDirective<{ min: 0; max: 150 }>]; }>; email: GqlField<string | null, { defaultValue: null; directives: [LengthDirective<{ min: 5; max: 255 }>]; }>; };

Generates:

input CreateUserInput { name: String! = "Anonymous" @length(min: 1, max: 100) age: Int! = 18 @range(min: 0, max: 150) email: String = null @length(min: 5, max: 255) }

Supported Default Value Types

Value typeExampleGraphQL output
String"hello""hello"
Number (Int)1010
Number (Float)3.143.14
Booleantrue, falsetrue, false
Nullnullnull
Array[1, 2, 3][1, 2, 3]
Object{ key: "value" }{key: "value"}
Enum"ACTIVE" (when field type is enum)ACTIVE

Literal Types Required

Default values must be specified as TypeScript literal types. Non-literal types will cause a warning:

// ✅ OK: Literal types export type GoodInput = { limit: GqlField<Int, { defaultValue: 10 }>; name: GqlField<string, { defaultValue: "default" }>; }; // ❌ Error: Non-literal types export type BadInput = { limit: GqlField<Int, { defaultValue: number }>; // Warning: must be literal name: GqlField<string, { defaultValue: string }>; // Warning: must be literal };

Excluding Fields

Use GqlObject with the ignoreFields option to exclude specific fields from the generated Input Object. This is useful for internal fields that should not be accepted from clients:

import { type GqlObject } from "@gqlkit-ts/runtime"; /** * Input for creating a user. */ export type CreateUserInput = GqlObject< { name: string; email: string; internalData: string; // Internal field - excluded from schema trackingId: string; // Internal field - excluded from schema }, { ignoreFields: "internalData" | "trackingId" } >;

Generates:

"""Input for creating a user.""" input CreateUserInput { name: String! email: String! }

Invalid Field Names

Input field names follow the same validation rules as object type fields. See Invalid Field Names for details.

Last updated on