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.address → UserProfileAddressInput).

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