Skip to content

Input Object Types

Input objects are used to represent the input arguments of a field. They are similar to object types, but they are used to represent inputs instead of output fields. Input object types use g.arg similar to how args are defined on output fields rather than using the g.field function like on output object types.

const
const UserCreateInput: GInputObjectType<{
name: GArg<GNonNull<GScalarType<string, string>>, false>;
email: GArg<GNonNull<GScalarType<string, string>>, false>;
}, false>
UserCreateInput
=
const g: GWithContext<Context>
g
.
inputObject: <{
name: GArg<GNonNull<GScalarType<string, string>>, false>;
email: GArg<GNonNull<GScalarType<string, string>>, false>;
}, false>(config: {
...;
}) => GInputObjectType<...>
inputObject
({
name: string
name
: "UserCreateInput",
fields: {
name: GArg<GNonNull<GScalarType<string, string>>, false>;
email: GArg<GNonNull<GScalarType<string, string>>, false>;
} | (() => {
name: GArg<GNonNull<GScalarType<string, string>>, false>;
email: GArg<GNonNull<GScalarType<string, string>>, false>;
})
fields
: {
name: GArg<GNonNull<GScalarType<string, string>>, false>
name
:
const g: GWithContext<Context>
g
.
arg: <GNonNull<GScalarType<string, string>>, undefined>(arg: {
type: GNonNull<GScalarType<string, string>>;
description?: Maybe<string>;
extensions?: (Readonly<...> & Readonly<...>) | ... 1 more ... | undefined;
astNode?: Maybe<...>;
deprecationReason?: Maybe<...>;
} & {
...;
}) => GArg<...>
arg
({
type: GNonNull<GScalarType<string, string>>
type
:
const g: GWithContext<Context>
g
.
nonNull: <GScalarType<string, string>>(of: GScalarType<string, string>) => GNonNull<GScalarType<string, string>>
nonNull
(
const g: GWithContext<Context>
g
.
type String: GScalarType<string, string>
String
) }),
email: GArg<GNonNull<GScalarType<string, string>>, false>
email
:
const g: GWithContext<Context>
g
.
arg: <GNonNull<GScalarType<string, string>>, undefined>(arg: {
type: GNonNull<GScalarType<string, string>>;
description?: Maybe<string>;
extensions?: (Readonly<...> & Readonly<...>) | ... 1 more ... | undefined;
astNode?: Maybe<...>;
deprecationReason?: Maybe<...>;
} & {
...;
}) => GArg<...>
arg
({
type: GNonNull<GScalarType<string, string>>
type
:
const g: GWithContext<Context>
g
.
nonNull: <GScalarType<string, string>>(of: GScalarType<string, string>) => GNonNull<GScalarType<string, string>>
nonNull
(
const g: GWithContext<Context>
g
.
type String: GScalarType<string, string>
String
) }),
},
});
const
const Mutation: GObjectType<unknown, Context>
Mutation
=
const g: GWithContext<Context>
g
.
object: <unknown>(youOnlyNeedToPassATypeParameterToThisFunctionYouPassTheActualRuntimeArgsOnTheResultOfThisFunction?: {
youOnlyNeedToPassATypeParameterToThisFunctionYouPassTheActualRuntimeArgsOnTheResultOfThisFunction: true;
}) => <Fields, Interfaces>(config: {
...;
} & Omit<...>) => GObjectType<...>
object
()({
name: string
name
: "Mutation",
fields: {
createUser: GField<unknown, {
input: GArg<GNonNull<GInputObjectType<{
name: GArg<GNonNull<GScalarType<string, string>>, false>;
email: GArg<GNonNull<GScalarType<string, string>>, false>;
}, false>>, false>;
}, GObjectType<...>, unknown, Context>;
} | (() => {
createUser: GField<unknown, {
input: GArg<GNonNull<GInputObjectType<{
name: GArg<GNonNull<GScalarType<string, string>>, false>;
email: GArg<GNonNull<GScalarType<string, string>>, false>;
}, false>>, false>;
}, GObjectType<...>, unknown, Context>;
})
fields
: {
createUser: GField<unknown, {
input: GArg<GNonNull<GInputObjectType<{
name: GArg<GNonNull<GScalarType<string, string>>, false>;
email: GArg<GNonNull<GScalarType<string, string>>, false>;
}, false>>, false>;
}, GObjectType<...>, unknown, Context>
createUser
:
const g: GWithContext<Context>
g
.
field: <unknown, GObjectType<UserSource, Context>, (source: unknown, args: {
readonly input: {
readonly name: string;
readonly email: string;
};
}, context: Context) => UserSource, {
...;
}>(field: FieldFuncArgs<...> & {
...;
}) => GField<...>
field
({
type: GObjectType<UserSource, Context>
type
:
const User: GObjectType<UserSource, Context>
User
,
args?: {
input: GArg<GNonNull<GInputObjectType<{
name: GArg<GNonNull<GScalarType<string, string>>, false>;
email: GArg<GNonNull<GScalarType<string, string>>, false>;
}, false>>, false>;
}
args
: {
input: GArg<GNonNull<GInputObjectType<{
name: GArg<GNonNull<GScalarType<string, string>>, false>;
email: GArg<GNonNull<GScalarType<string, string>>, false>;
}, false>>, false>
input
:
const g: GWithContext<Context>
g
.
arg: <GNonNull<GInputObjectType<{
name: GArg<GNonNull<GScalarType<string, string>>, false>;
email: GArg<GNonNull<GScalarType<string, string>>, false>;
}, false>>, undefined>(arg: {
...;
} & {
...;
}) => GArg<...>
arg
({
type: GNonNull<GInputObjectType<{
name: GArg<GNonNull<GScalarType<string, string>>, false>;
email: GArg<GNonNull<GScalarType<string, string>>, false>;
}, false>>
type
:
const g: GWithContext<Context>
g
.
nonNull: <GInputObjectType<{
name: GArg<GNonNull<GScalarType<string, string>>, false>;
email: GArg<GNonNull<GScalarType<string, string>>, false>;
}, false>>(of: GInputObjectType<...>) => GNonNull<...>
nonNull
(
const UserCreateInput: GInputObjectType<{
name: GArg<GNonNull<GScalarType<string, string>>, false>;
email: GArg<GNonNull<GScalarType<string, string>>, false>;
}, false>
UserCreateInput
) }),
},
resolve: ((source: unknown, args: {
readonly input: {
readonly name: string;
readonly email: string;
};
}, context: Context, info: GraphQLResolveInfo) => InferValueFromOutputType<...>) & ((source: unknown, args: {
...;
}, context: Context) => UserSource)
resolve
: (
source: unknown
source
,
args: {
readonly input: {
readonly name: string;
readonly email: string;
};
}
args
,
context: Context
context
) => {
return
context: Context
context
.
createUser: (input: {
name: string;
email: string;
}) => UserSource
createUser
(
args: {
readonly input: {
readonly name: string;
readonly email: string;
};
}
args
.input);
input: {
readonly name: string;
readonly email: string;
}
},
}),
},
});

Circular Types

While circular input object types are less common than circular Object Types, they can still occur. Just like with circular object types, we need to start by making fields a function:

const UserCreateInput =
const g: GWithContext<unknown>
g
.
inputObject: <any, false>(config: {
name: string;
description?: Maybe<string>;
extensions?: Maybe<Readonly<GraphQLInputObjectTypeExtensions>>;
astNode?: Maybe<...>;
extensionASTNodes?: Maybe<...>;
isOneOf?: false;
fields: any;
}) => GInputObjectType<...>
inputObject
({
Error ts(7022) ― 'UserCreateInput' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.
name: string
name
: "UserCreateInput",
fields: () => ({
Error ts(7023) ― 'fields' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.
name: GArg<GNonNull<GScalarType<string, string>>, false>
name
:
const g: GWithContext<unknown>
g
.
arg: <GNonNull<GScalarType<string, string>>, undefined>(arg: {
type: GNonNull<GScalarType<string, string>>;
description?: Maybe<string>;
extensions?: (Readonly<...> & Readonly<...>) | ... 1 more ... | undefined;
astNode?: Maybe<...>;
deprecationReason?: Maybe<...>;
} & {
...;
}) => GArg<...>
arg
({
type: GNonNull<GScalarType<string, string>>
type
:
const g: GWithContext<unknown>
g
.
nonNull: <GScalarType<string, string>>(of: GScalarType<string, string>) => GNonNull<GScalarType<string, string>>
nonNull
(
const g: GWithContext<unknown>
g
.
type String: GScalarType<string, string>
String
) }),
email: GArg<GNonNull<GScalarType<string, string>>, false>
email
:
const g: GWithContext<unknown>
g
.
arg: <GNonNull<GScalarType<string, string>>, undefined>(arg: {
type: GNonNull<GScalarType<string, string>>;
description?: Maybe<string>;
extensions?: (Readonly<...> & Readonly<...>) | ... 1 more ... | undefined;
astNode?: Maybe<...>;
deprecationReason?: Maybe<...>;
} & {
...;
}) => GArg<...>
arg
({
type: GNonNull<GScalarType<string, string>>
type
:
const g: GWithContext<unknown>
g
.
nonNull: <GScalarType<string, string>>(of: GScalarType<string, string>) => GNonNull<GScalarType<string, string>>
nonNull
(
const g: GWithContext<unknown>
g
.
type String: GScalarType<string, string>
String
) }),
friends: GArg<GList<GNonNull<any>>, false>
friends
:
const g: GWithContext<unknown>
g
.
arg: <GList<GNonNull<any>>, undefined>(arg: {
type: GList<GNonNull<any>>;
description?: Maybe<string>;
extensions?: (Readonly<GraphQLInputFieldExtensions> & Readonly<...>) | null | undefined;
astNode?: Maybe<...>;
deprecationReason?: Maybe<...>;
} & {
...;
}) => GArg<...>
arg
({
type: GList<GNonNull<any>>
type
:
const g: GWithContext<unknown>
g
.
list: <GNonNull<any>>(of: GNonNull<any>) => GList<GNonNull<any>>
list
(
const g: GWithContext<unknown>
g
.
nonNull: <any>(of: any) => GNonNull<any>
nonNull
(
const UserCreateInput: any
UserCreateInput
)) }),
}),
});

To resolve TypeScript’s errors about circularity though, we unfortunately can’t use the g type like we did with object types. Instead, we need to use the GInputObjectType type and we also need to essentially duplicate the fields definition in the types

import type {
type GArg<Type extends GInputType, HasDefaultValue extends boolean = boolean> = {
type: Type;
defaultValue: {
true: {} | null;
false: undefined;
}[`${HasDefaultValue}`];
description?: Maybe<string>;
deprecationReason?: Maybe<string>;
extensions?: Maybe<...>;
astNode?: Maybe<...>;
}
GArg
,
class GNonNull<Of extends GNullableType<any>>
GNonNull
,
class GList<Of extends GType<any>>
GList
,
class GInputObjectType<Fields extends { [key: string]: IsOneOf extends true ? GArg<GNullableInputType, false> : GArg<GInputType>; }, IsOneOf extends boolean = false>
GInputObjectType
,
} from "@graphql-ts/schema";
type
type UserCreateInput = GInputObjectType<{
name: GArg<GNonNull<typeof g.String>>;
email: g<typeof g.arg<g<typeof g.nonNull<typeof g.String>>>>;
friends: GArg<GList<GNonNull<UserCreateInput>>>;
}, false>
UserCreateInput
=
class GInputObjectType<Fields extends { [key: string]: IsOneOf extends true ? GArg<GNullableInputType, false> : GArg<GInputType>; }, IsOneOf extends boolean = false>
GInputObjectType
<{
// you can use the G* types from @graphql-ts/schema to define the fields
name: GArg<GNonNull<GScalarType<string, string>>>
name
:
type GArg<Type extends GInputType, HasDefaultValue extends boolean = boolean> = {
type: Type;
defaultValue: {
true: {} | null;
false: undefined;
}[`${HasDefaultValue}`];
description?: Maybe<string>;
deprecationReason?: Maybe<string>;
extensions?: Maybe<...>;
astNode?: Maybe<...>;
}
GArg
<
class GNonNull<Of extends GNullableType<any>>
GNonNull
<typeof
const g: GWithContext<unknown>
g
.
type String: GScalarType<string, string>
String
>>;
// or you can use the g type and g.* functions
email: GArg<GNonNull<GScalarType<string, string>>, false>
email
:
type g<T> = T extends () => (args: any) => infer R ? R : T extends (args: any) => infer R ? R : never
g
<typeof
const g: GWithContext<unknown>
g
.
arg: <Type extends GInputType, DefaultValue extends InferValueFromInputType<Type> | undefined = undefined>(arg: {
...;
} & (undefined extends DefaultValue ? {
defaultValue?: DefaultValue;
} : {
defaultValue: DefaultValue;
})) => GArg<Type, DefaultValue extends undefined ? false : true>
arg
<
type g<T> = T extends () => (args: any) => infer R ? R : T extends (args: any) => infer R ? R : never
g
<typeof
const g: GWithContext<unknown>
g
.
nonNull: <Of extends GNullableType<any>>(of: Of) => GNonNull<Of>
nonNull
<typeof
const g: GWithContext<unknown>
g
.
type String: GScalarType<string, string>
String
>>>>;
friends: GArg<GList<GNonNull<UserCreateInput>>>
friends
:
type GArg<Type extends GInputType, HasDefaultValue extends boolean = boolean> = {
type: Type;
defaultValue: {
true: {} | null;
false: undefined;
}[`${HasDefaultValue}`];
description?: Maybe<string>;
deprecationReason?: Maybe<string>;
extensions?: Maybe<...>;
astNode?: Maybe<...>;
}
GArg
<
class GList<Of extends GType<any>>
GList
<
class GNonNull<Of extends GNullableType<any>>
GNonNull
<
type UserCreateInput = GInputObjectType<{
name: GArg<GNonNull<typeof g.String>>;
email: g<typeof g.arg<g<typeof g.nonNull<typeof g.String>>>>;
friends: GArg<GList<GNonNull<UserCreateInput>>>;
}, false>
UserCreateInput
>>>;
}>;
const
const UserCreateInput: UserCreateInput
UserCreateInput
:
type UserCreateInput = GInputObjectType<{
name: GArg<GNonNull<typeof g.String>>;
email: g<typeof g.arg<g<typeof g.nonNull<typeof g.String>>>>;
friends: GArg<GList<GNonNull<UserCreateInput>>>;
}, false>
UserCreateInput
=
const g: GWithContext<unknown>
g
.
inputObject: <{
name: GArg<GNonNull<GScalarType<string, string>>, false>;
email: GArg<GNonNull<GScalarType<string, string>>, false>;
friends: GArg<...>;
}, false>(config: {
...;
}) => GInputObjectType<...>
inputObject
({
name: string
name
: "UserCreateInput",
fields: {
name: GArg<GNonNull<GScalarType<string, string>>, false>;
email: GArg<GNonNull<GScalarType<string, string>>, false>;
friends: GArg<...>;
} | (() => {
name: GArg<GNonNull<GScalarType<string, string>>, false>;
email: GArg<GNonNull<GScalarType<string, string>>, false>;
friends: GArg<...>;
})
fields
: () => ({
name: GArg<GNonNull<GScalarType<string, string>>, false>
name
:
const g: GWithContext<unknown>
g
.
arg: <GNonNull<GScalarType<string, string>>, undefined>(arg: {
type: GNonNull<GScalarType<string, string>>;
description?: Maybe<string>;
deprecationReason?: Maybe<...>;
extensions?: (Readonly<...> & Readonly<...>) | ... 1 more ... | undefined;
astNode?: Maybe<...>;
} & {
...;
}) => GArg<...>
arg
({
type: GNonNull<GScalarType<string, string>>
type
:
const g: GWithContext<unknown>
g
.
nonNull: <GScalarType<string, string>>(of: GScalarType<string, string>) => GNonNull<GScalarType<string, string>>
nonNull
(
const g: GWithContext<unknown>
g
.
type String: GScalarType<string, string>
String
) }),
email: GArg<GNonNull<GScalarType<string, string>>, false>
email
:
const g: GWithContext<unknown>
g
.
arg: <GNonNull<GScalarType<string, string>>, undefined>(arg: {
type: GNonNull<GScalarType<string, string>>;
description?: Maybe<string>;
deprecationReason?: Maybe<...>;
extensions?: (Readonly<...> & Readonly<...>) | ... 1 more ... | undefined;
astNode?: Maybe<...>;
} & {
...;
}) => GArg<...>
arg
({
type: GNonNull<GScalarType<string, string>>
type
:
const g: GWithContext<unknown>
g
.
nonNull: <GScalarType<string, string>>(of: GScalarType<string, string>) => GNonNull<GScalarType<string, string>>
nonNull
(
const g: GWithContext<unknown>
g
.
type String: GScalarType<string, string>
String
) }),
friends: GArg<GList<GNonNull<UserCreateInput>>, false>
friends
:
const g: GWithContext<unknown>
g
.
arg: <GList<GNonNull<UserCreateInput>>, undefined>(arg: {
type: GList<GNonNull<UserCreateInput>>;
description?: Maybe<...>;
deprecationReason?: Maybe<...>;
extensions?: (Readonly<...> & Readonly<...>) | ... 1 more ... | undefined;
astNode?: Maybe<...>;
} & {
...;
}) => GArg<...>
arg
({
type: GList<GNonNull<UserCreateInput>>
type
:
const g: GWithContext<unknown>
g
.
list: <GNonNull<UserCreateInput>>(of: GNonNull<UserCreateInput>) => GList<GNonNull<UserCreateInput>>
list
(
const g: GWithContext<unknown>
g
.
nonNull: <UserCreateInput>(of: UserCreateInput) => GNonNull<UserCreateInput>
nonNull
(
const UserCreateInput: UserCreateInput
UserCreateInput
)) }),
}),
});

Since most fields in input objects won’t be circular, you can also extract out the non-circular fields and use typeof instead of duplicating the fields:

import type {
type GArg<Type extends GInputType, HasDefaultValue extends boolean = boolean> = {
type: Type;
defaultValue: {
true: {} | null;
false: undefined;
}[`${HasDefaultValue}`];
description?: Maybe<string>;
deprecationReason?: Maybe<string>;
extensions?: Maybe<...>;
astNode?: Maybe<...>;
}
GArg
,
class GNonNull<Of extends GNullableType<any>>
GNonNull
,
class GList<Of extends GType<any>>
GList
,
class GInputObjectType<Fields extends { [key: string]: IsOneOf extends true ? GArg<GNullableInputType, false> : GArg<GInputType>; }, IsOneOf extends boolean = false>
GInputObjectType
,
} from "@graphql-ts/schema";
const
const userCreateInputFields: {
name: GArg<GNonNull<GScalarType<string, string>>, false>;
email: GArg<GNonNull<GScalarType<string, string>>, false>;
}
userCreateInputFields
= {
name: GArg<GNonNull<GScalarType<string, string>>, false>
name
:
const g: GWithContext<unknown>
g
.
arg: <GNonNull<GScalarType<string, string>>, undefined>(arg: {
type: GNonNull<GScalarType<string, string>>;
description?: Maybe<string>;
deprecationReason?: Maybe<...>;
extensions?: (Readonly<...> & Readonly<...>) | ... 1 more ... | undefined;
astNode?: Maybe<...>;
} & {
...;
}) => GArg<...>
arg
({
type: GNonNull<GScalarType<string, string>>
type
:
const g: GWithContext<unknown>
g
.
nonNull: <GScalarType<string, string>>(of: GScalarType<string, string>) => GNonNull<GScalarType<string, string>>
nonNull
(
const g: GWithContext<unknown>
g
.
type String: GScalarType<string, string>
String
) }),
email: GArg<GNonNull<GScalarType<string, string>>, false>
email
:
const g: GWithContext<unknown>
g
.
arg: <GNonNull<GScalarType<string, string>>, undefined>(arg: {
type: GNonNull<GScalarType<string, string>>;
description?: Maybe<string>;
deprecationReason?: Maybe<...>;
extensions?: (Readonly<...> & Readonly<...>) | ... 1 more ... | undefined;
astNode?: Maybe<...>;
} & {
...;
}) => GArg<...>
arg
({
type: GNonNull<GScalarType<string, string>>
type
:
const g: GWithContext<unknown>
g
.
nonNull: <GScalarType<string, string>>(of: GScalarType<string, string>) => GNonNull<GScalarType<string, string>>
nonNull
(
const g: GWithContext<unknown>
g
.
type String: GScalarType<string, string>
String
) }),
};
type
type UserCreateInput = GInputObjectType<{
name: GArg<GNonNull<GScalarType<string, string>>, false>;
email: GArg<GNonNull<GScalarType<string, string>>, false>;
} & {
...;
}, false>
UserCreateInput
=
class GInputObjectType<Fields extends { [key: string]: IsOneOf extends true ? GArg<GNullableInputType, false> : GArg<GInputType>; }, IsOneOf extends boolean = false>
GInputObjectType
<
typeof
const userCreateInputFields: {
name: GArg<GNonNull<GScalarType<string, string>>, false>;
email: GArg<GNonNull<GScalarType<string, string>>, false>;
}
userCreateInputFields
& {
friends: GArg<GList<GNonNull<UserCreateInput>>>
friends
:
type GArg<Type extends GInputType, HasDefaultValue extends boolean = boolean> = {
type: Type;
defaultValue: {
true: {} | null;
false: undefined;
}[`${HasDefaultValue}`];
description?: Maybe<string>;
deprecationReason?: Maybe<string>;
extensions?: Maybe<...>;
astNode?: Maybe<...>;
}
GArg
<
class GList<Of extends GType<any>>
GList
<
class GNonNull<Of extends GNullableType<any>>
GNonNull
<
type UserCreateInput = GInputObjectType<{
name: GArg<GNonNull<GScalarType<string, string>>, false>;
email: GArg<GNonNull<GScalarType<string, string>>, false>;
} & {
...;
}, false>
UserCreateInput
>>>;
}
>;
const
const UserCreateInput: UserCreateInput
UserCreateInput
:
type UserCreateInput = GInputObjectType<{
name: GArg<GNonNull<GScalarType<string, string>>, false>;
email: GArg<GNonNull<GScalarType<string, string>>, false>;
} & {
...;
}, false>
UserCreateInput
=
const g: GWithContext<unknown>
g
.
inputObject: <{
friends: GArg<GList<GNonNull<UserCreateInput>>, false>;
name: GArg<GNonNull<GScalarType<string, string>>, false>;
email: GArg<...>;
}, false>(config: {
...;
}) => GInputObjectType<...>
inputObject
({
name: string
name
: "UserCreateInput",
fields: {
friends: GArg<GList<GNonNull<UserCreateInput>>, false>;
name: GArg<GNonNull<GScalarType<string, string>>, false>;
email: GArg<...>;
} | (() => {
friends: GArg<GList<GNonNull<UserCreateInput>>, false>;
name: GArg<GNonNull<GScalarType<string, string>>, false>;
email: GArg<...>;
})
fields
: () => ({
...
const userCreateInputFields: {
name: GArg<GNonNull<GScalarType<string, string>>, false>;
email: GArg<GNonNull<GScalarType<string, string>>, false>;
}
userCreateInputFields
,
friends: GArg<GList<GNonNull<UserCreateInput>>, false>
friends
:
const g: GWithContext<unknown>
g
.
arg: <GList<GNonNull<UserCreateInput>>, undefined>(arg: {
type: GList<GNonNull<UserCreateInput>>;
description?: Maybe<...>;
deprecationReason?: Maybe<...>;
extensions?: (Readonly<...> & Readonly<...>) | ... 1 more ... | undefined;
astNode?: Maybe<...>;
} & {
...;
}) => GArg<...>
arg
({
type: GList<GNonNull<UserCreateInput>>
type
:
const g: GWithContext<unknown>
g
.
list: <GNonNull<UserCreateInput>>(of: GNonNull<UserCreateInput>) => GList<GNonNull<UserCreateInput>>
list
(
const g: GWithContext<unknown>
g
.
nonNull: <UserCreateInput>(of: UserCreateInput) => GNonNull<UserCreateInput>
nonNull
(
const UserCreateInput: UserCreateInput
UserCreateInput
)) }),
}),
});

Nullability & Default Values

Input objects can also have default values for their arguments. Default values are used when the argument is not provided in the input object. Default values can be provided using the defaultValue property in the g.arg function. We’re going to demonstrate by using args on a field rather than on an input object type but the same concept applies to input object types.

To start with, since all types are nullable in GraphQL by default, let’s look at what the type of a nullable type is:

const
const field: GField<unknown, {
name: GArg<GScalarType<string, string>, false>;
}, GScalarType<string, string>, unknown, unknown>
field
=
const g: GWithContext<unknown>
g
.
field: <unknown, GScalarType<string, string>, (_: unknown, args: {
readonly name: string | null | undefined;
}) => string | null | undefined, {
name: GArg<GScalarType<string, string>, false>;
}>(field: FieldFuncArgs<...> & {
...;
}) => GField<...>
field
({
type: GScalarType<string, string>
type
:
const g: GWithContext<unknown>
g
.
type String: GScalarType<string, string>
String
,
args?: {
name: GArg<GScalarType<string, string>, false>;
}
args
: {
name: GArg<GScalarType<string, string>, false>
name
:
const g: GWithContext<unknown>
g
.
arg: <GScalarType<string, string>, undefined>(arg: {
type: GScalarType<string, string>;
description?: Maybe<string>;
deprecationReason?: Maybe<string>;
extensions?: (Readonly<...> & Readonly<...>) | ... 1 more ... | undefined;
astNode?: Maybe<...>;
} & {
...;
}) => GArg<...>
arg
({
type: GScalarType<string, string>
type
:
const g: GWithContext<unknown>
g
.
type String: GScalarType<string, string>
String
}),
},
resolve: ((source: unknown, args: {
readonly name: string | null | undefined;
}, context: unknown, info: GraphQLResolveInfo) => InferValueFromOutputType<GScalarType<string, string>>) & ((_: unknown, args: {
...;
}) => string | ... 1 more ... | undefined)
resolve
(
_: unknown
_
, args) {
args: {
readonly name: string | null | undefined;
}
return
args: {
readonly name: string | null | undefined;
}
args
.
name: string | null | undefined
name
;
},
});

For the String scalar, the type is string | null | undefined.

This is because for a nullable input type, there are three possible options for a consumer of a GraphQL API:

query {
withoutName: field # represented as `undefined` in resolvers
withNull: field(name: null)
withValue: field(name: "string")
}

For a nullable input type, adding a defaultValue will remove the undefined option but note that it will not remove null.

const g: GWithContext<unknown>
g
.
field: <unknown, GScalarType<string, string>, (_: unknown, args: {
readonly name: string | null;
}) => string | null, {
name: GArg<GScalarType<string, string>, true>;
}>(field: FieldFuncArgs<...> & {
...;
}) => GField<...>
field
({
type: GScalarType<string, string>
type
:
const g: GWithContext<unknown>
g
.
type String: GScalarType<string, string>
String
,
args?: {
name: GArg<GScalarType<string, string>, true>;
}
args
: {
name: GArg<GScalarType<string, string>, true>
name
:
const g: GWithContext<unknown>
g
.
arg: <GScalarType<string, string>, string>(arg: {
type: GScalarType<string, string>;
description?: Maybe<string>;
deprecationReason?: Maybe<string>;
extensions?: (Readonly<...> & Readonly<...>) | ... 1 more ... | undefined;
astNode?: Maybe<...>;
} & {
...;
}) => GArg<...>
arg
({
type: GScalarType<string, string>
type
:
const g: GWithContext<unknown>
g
.
type String: GScalarType<string, string>
String
,
defaultValue: string
defaultValue
: "name"
}),
},
resolve: ((source: unknown, args: {
readonly name: string | null;
}, context: unknown, info: GraphQLResolveInfo) => InferValueFromOutputType<GScalarType<string, string>>) & ((_: unknown, args: {
...;
}) => string | null)
resolve
(
_: unknown
_
, args) {
args: {
readonly name: string | null;
}
return
args: {
readonly name: string | null;
}
args
.
name: string | null
name
;
},
});

For non-nullable input types, adding a defaultValue doesn’t affect the type received by the resolve function, it just allows the consumer to not provide the argument in which case the default value will be used:

const g: GWithContext<unknown>
g
.
field: <unknown, GScalarType<string, string>, (_: unknown, args: {
readonly name: string;
}) => string, {
name: GArg<GNonNull<GScalarType<string, string>>, true>;
}>(field: FieldFuncArgs<...> & {
...;
}) => GField<...>
field
({
type: GScalarType<string, string>
type
:
const g: GWithContext<unknown>
g
.
type String: GScalarType<string, string>
String
,
args?: {
name: GArg<GNonNull<GScalarType<string, string>>, true>;
}
args
: {
name: GArg<GNonNull<GScalarType<string, string>>, true>
name
:
const g: GWithContext<unknown>
g
.
arg: <GNonNull<GScalarType<string, string>>, string>(arg: {
type: GNonNull<GScalarType<string, string>>;
description?: Maybe<string>;
deprecationReason?: Maybe<...>;
extensions?: (Readonly<...> & Readonly<...>) | ... 1 more ... | undefined;
astNode?: Maybe<...>;
} & {
...;
}) => GArg<...>
arg
({
type: GNonNull<GScalarType<string, string>>
type
:
const g: GWithContext<unknown>
g
.
nonNull: <GScalarType<string, string>>(of: GScalarType<string, string>) => GNonNull<GScalarType<string, string>>
nonNull
(
const g: GWithContext<unknown>
g
.
type String: GScalarType<string, string>
String
),
defaultValue: string
defaultValue
: "name" }),
},
resolve: ((source: unknown, args: {
readonly name: string;
}, context: unknown, info: GraphQLResolveInfo) => InferValueFromOutputType<GScalarType<string, string>>) & ((_: unknown, args: {
...;
}) => string)
resolve
(
_: unknown
_
, args) {
args: {
readonly name: string;
}
return
args: {
readonly name: string;
}
args
.
name: string
name
;
},
});

One Of

To express an input object where a consumer must provide exactly one of the keys, you can use isOneOf. Note all the fields must be nullable when defining the type but in your resolver, exactly one key will be provided and it will be non-null and no other keys will be provided.

const
const UserCreateInput: GInputObjectType<{
id: GArg<GScalarType<string, string>, false>;
email: GArg<GScalarType<string, string>, false>;
name: GArg<GScalarType<string, string>, false>;
}, true>
UserCreateInput
=
const g: GWithContext<unknown>
g
.
inputObject: <{
id: GArg<GScalarType<string, string>, false>;
email: GArg<GScalarType<string, string>, false>;
name: GArg<GScalarType<string, string>, false>;
}, true>(config: GInputObjectTypeConfig<...>) => GInputObjectType<...>
inputObject
({
name: string
name
: "UserSearchInput",
isOneOf: true | undefined
isOneOf
: true,
fields: {
id: GArg<GScalarType<string, string>, false>;
email: GArg<GScalarType<string, string>, false>;
name: GArg<GScalarType<string, string>, false>;
} | (() => {
id: GArg<GScalarType<string, string>, false>;
email: GArg<GScalarType<string, string>, false>;
name: GArg<GScalarType<string, string>, false>;
})
fields
: {
id: GArg<GScalarType<string, string>, false>
id
:
const g: GWithContext<unknown>
g
.
arg: <GScalarType<string, string>, undefined>(arg: {
type: GScalarType<string, string>;
description?: Maybe<string>;
extensions?: (Readonly<GraphQLInputFieldExtensions> & Readonly<...>) | null | undefined;
astNode?: Maybe<...>;
deprecationReason?: Maybe<...>;
} & {
...;
}) => GArg<...>
arg
({
type: GScalarType<string, string>
type
:
const g: GWithContext<unknown>
g
.
type ID: GScalarType<string, string>
ID
}),
email: GArg<GScalarType<string, string>, false>
email
:
const g: GWithContext<unknown>
g
.
arg: <GScalarType<string, string>, undefined>(arg: {
type: GScalarType<string, string>;
description?: Maybe<string>;
extensions?: (Readonly<GraphQLInputFieldExtensions> & Readonly<...>) | null | undefined;
astNode?: Maybe<...>;
deprecationReason?: Maybe<...>;
} & {
...;
}) => GArg<...>
arg
({
type: GScalarType<string, string>
type
:
const g: GWithContext<unknown>
g
.
type String: GScalarType<string, string>
String
}),
name: GArg<GScalarType<string, string>, false>
name
:
const g: GWithContext<unknown>
g
.
arg: <GScalarType<string, string>, undefined>(arg: {
type: GScalarType<string, string>;
description?: Maybe<string>;
extensions?: (Readonly<GraphQLInputFieldExtensions> & Readonly<...>) | null | undefined;
astNode?: Maybe<...>;
deprecationReason?: Maybe<...>;
} & {
...;
}) => GArg<...>
arg
({
type: GScalarType<string, string>
type
:
const g: GWithContext<unknown>
g
.
type String: GScalarType<string, string>
String
}),
},
});
const
const search: GField<unknown, {
input: GArg<GNonNull<GInputObjectType<{
id: GArg<GScalarType<string, string>, false>;
email: GArg<GScalarType<string, string>, false>;
name: GArg<GScalarType<string, string>, false>;
}, true>>, false>;
}, GObjectType<...>, unknown, unknown>
search
=
const g: GWithContext<unknown>
g
.
field: <unknown, GObjectType<UserSource, unknown>, (_: unknown, args: {
readonly input: {
readonly name: string;
readonly id?: never;
readonly email?: never;
} | {
readonly id: string;
readonly name?: never;
readonly email?: never;
} | {
...;
};
}) => null, {
...;
}>(field: FieldFuncArgs<...> & {
...;
}) => GField<...>
field
({
type: GObjectType<UserSource, unknown>
type
:
const User: GObjectType<UserSource, unknown>
User
,
args?: {
input: GArg<GNonNull<GInputObjectType<{
id: GArg<GScalarType<string, string>, false>;
email: GArg<GScalarType<string, string>, false>;
name: GArg<GScalarType<string, string>, false>;
}, true>>, false>;
}
args
: {
input: GArg<GNonNull<GInputObjectType<{
id: GArg<GScalarType<string, string>, false>;
email: GArg<GScalarType<string, string>, false>;
name: GArg<GScalarType<string, string>, false>;
}, true>>, false>
input
:
const g: GWithContext<unknown>
g
.
arg: <GNonNull<GInputObjectType<{
id: GArg<GScalarType<string, string>, false>;
email: GArg<GScalarType<string, string>, false>;
name: GArg<GScalarType<string, string>, false>;
}, true>>, undefined>(arg: {
...;
} & {
...;
}) => GArg<...>
arg
({
type: GNonNull<GInputObjectType<{
id: GArg<GScalarType<string, string>, false>;
email: GArg<GScalarType<string, string>, false>;
name: GArg<GScalarType<string, string>, false>;
}, true>>
type
:
const g: GWithContext<unknown>
g
.
nonNull: <GInputObjectType<{
id: GArg<GScalarType<string, string>, false>;
email: GArg<GScalarType<string, string>, false>;
name: GArg<GScalarType<string, string>, false>;
}, true>>(of: GInputObjectType<...>) => GNonNull<...>
nonNull
(
const UserCreateInput: GInputObjectType<{
id: GArg<GScalarType<string, string>, false>;
email: GArg<GScalarType<string, string>, false>;
name: GArg<GScalarType<string, string>, false>;
}, true>
UserCreateInput
) }),
},
resolve: ((source: unknown, args: {
readonly input: {
readonly name: string;
readonly id?: never;
readonly email?: never;
} | {
readonly id: string;
readonly name?: never;
readonly email?: never;
} | {
readonly email: string;
readonly name?: never;
readonly id?: never;
};
}, context: unknown, info: GraphQLResolveInfo) => InferValueFromOutputType<...>) & ((_: unknown, args: {
...;
}) => null)
resolve
(
_: unknown
_
,
args: {
readonly input: {
readonly name: string;
readonly id?: never;
readonly email?: never;
} | {
readonly id: string;
readonly name?: never;
readonly email?: never;
} | {
readonly email: string;
readonly name?: never;
readonly id?: never;
};
}
args
) {
var console: Console
console
.
Console.log(...data: any[]): void
log
(
args: {
readonly input: {
readonly name: string;
readonly id?: never;
readonly email?: never;
} | {
readonly id: string;
readonly name?: never;
readonly email?: never;
} | {
readonly email: string;
readonly name?: never;
readonly id?: never;
};
}
args
.input);
input: {
readonly name: string;
readonly id?: never;
readonly email?: never;
} | {
readonly id: string;
readonly name?: never;
readonly email?: never;
} | {
readonly email: string;
readonly name?: never;
readonly id?: never;
}
return null;
},
});