Skip to content

Object Types

Object types are the most common type in GraphQL. They represent a type with a set of fields that you can query. In @graphql-ts/schema, you can define object types using the g.object function.

To define an object type, you need to provide a source type that represents the shape of the object type on the server. Note this type doesn’t have to align with the GraphQL fields.

type
type UserSource = {
id: string;
name: string;
}
UserSource
= {
id: string
id
: string;
name: string
name
: string;
};
const
const User: GObjectType<UserSource, unknown>
User
=
const g: GWithContext<unknown>
g
.
object: <UserSource>(youOnlyNeedToPassATypeParameterToThisFunctionYouPassTheActualRuntimeArgsOnTheResultOfThisFunction?: {
youOnlyNeedToPassATypeParameterToThisFunctionYouPassTheActualRuntimeArgsOnTheResultOfThisFunction: true;
}) => <Fields, Interfaces>(config: {
...;
} & Omit<...>) => GObjectType<...>
object
<
type UserSource = {
id: string;
name: string;
}
UserSource
>()({
name: string
name
: "User",
});

Then we can define the fields of the object type. The fields object is a map of field names to field definitions. The field definitions are created using the g.field function.

const
const User: GObjectType<UserSource, unknown>
User
=
const g: GWithContext<unknown>
g
.
object: <UserSource>(youOnlyNeedToPassATypeParameterToThisFunctionYouPassTheActualRuntimeArgsOnTheResultOfThisFunction?: {
youOnlyNeedToPassATypeParameterToThisFunctionYouPassTheActualRuntimeArgsOnTheResultOfThisFunction: true;
}) => <Fields, Interfaces>(config: {
...;
} & Omit<...>) => GObjectType<...>
object
<
type UserSource = {
id: string;
name: string;
}
UserSource
>()({
name: string
name
: "User",
fields: {
id: GField<UserSource, any, GNonNull<GScalarType<string, string>>, ImpliedResolver<any, GNonNull<GScalarType<string, string>>, unknown>, unknown>;
name: GField<...>;
} | (() => {
id: GField<UserSource, any, GNonNull<GScalarType<string, string>>, ImpliedResolver<any, GNonNull<GScalarType<string, string>>, unknown>, unknown>;
name: GField<...>;
})
fields
: {
id: GField<UserSource, any, GNonNull<GScalarType<string, string>>, ImpliedResolver<any, GNonNull<GScalarType<string, string>>, unknown>, unknown>
id
:
const g: GWithContext<unknown>
g
.
field: <UserSource, GNonNull<GScalarType<string, string>>, unknown, any>(field: FieldFuncArgs<UserSource, any, GNonNull<GScalarType<string, string>>, unknown> & {
...;
}) => GField<...>
field
({
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 ID: GScalarType<string, string>
ID
) }),
name: GField<UserSource, any, GNonNull<GScalarType<string, string>>, ImpliedResolver<any, GNonNull<GScalarType<string, string>>, unknown>, unknown>
name
:
const g: GWithContext<unknown>
g
.
field: <UserSource, GNonNull<GScalarType<string, string>>, unknown, any>(field: FieldFuncArgs<UserSource, any, GNonNull<GScalarType<string, string>>, unknown> & {
...;
}) => GField<...>
field
({
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
) }),
},
});

Since the UserSource type in this case aligns with the GraphQL fields, we don’t need to provide a resolve function for the fields. This isn’t always the case though, if we add a field that doesn’t exist on the UserSource type, we’ll receive a TypeScript error:

const
const User: GObjectType<UserSource, unknown>
User
=
const g: GWithContext<unknown>
g
.
object: <UserSource>(youOnlyNeedToPassATypeParameterToThisFunctionYouPassTheActualRuntimeArgsOnTheResultOfThisFunction?: {
youOnlyNeedToPassATypeParameterToThisFunctionYouPassTheActualRuntimeArgsOnTheResultOfThisFunction: true;
}) => <Fields, Interfaces>(config: {
...;
} & Omit<...>) => GObjectType<...>
object
<
type UserSource = {
id: string;
name: string;
}
UserSource
>()({
name: string
name
: "User",
fields: ({
id: GField<UserSource, any, any, string, unknown>;
name: GField<UserSource, any, any, string, unknown>;
nameBackwards: GField<UserSource, any, any, unknown, unknown>;
} & InterfaceFieldsToOutputFields<...>) | (() => {
id: GField<UserSource, any, any, string, unknown>;
name: GField<UserSource, any, any, string, unknown>;
nameBackwards: GField<UserSource, any, any, unknown, unknown>;
} & InterfaceFieldsToOutputFields<...>)
fields
: {
id: GField<UserSource, any, any, string, unknown>
id
:
const g: GWithContext<unknown>
g
.
field: <UserSource, GNonNull<GScalarType<string, string>>, unknown, any>(field: FieldFuncArgs<UserSource, any, GNonNull<GScalarType<string, string>>, unknown> & {
...;
}) => GField<...>
field
({
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 ID: GScalarType<string, string>
ID
) }),
name: GField<UserSource, any, GNonNull<GScalarType<string, string>>, ImpliedResolver<any, GNonNull<GScalarType<string, string>>, unknown>, unknown>
name
:
const g: GWithContext<unknown>
g
.
field: <UserSource, GNonNull<GScalarType<string, string>>, unknown, any>(field: FieldFuncArgs<UserSource, any, GNonNull<GScalarType<string, string>>, unknown> & {
...;
}) => GField<...>
field
({
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
) }),
nameBackwards:
const g: GWithContext<unknown>
g
.
field: <UserSource, GNonNull<GScalarType<string, string>>, unknown, any>(field: FieldFuncArgs<UserSource, any, GNonNull<GScalarType<string, string>>, unknown> & {
...;
}) => GField<...>
field
({
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
) }),
Error ts(2375) ― Type 'GField<UserSource, any, GNonNull<GScalarType<string, string>>, ImpliedResolver<any, GNonNull<GScalarType<string, string>>, unknown>, unknown>' is not assignable to type 'GField<UserSource, any, any, unknown, unknown>' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties. Types of property '__missingResolve' are incompatible. Type '((arg: ImpliedResolver<any, GNonNull<GScalarType<string, string>>, unknown>) => void) | undefined' is not assignable to type '((arg: unknown) => void) | undefined'. Type '(arg: ImpliedResolver<any, GNonNull<GScalarType<string, string>>, unknown>) => void' is not assignable to type '(arg: unknown) => void'. Types of parameters 'arg' and 'arg' are incompatible. Type 'unknown' is not assignable to type 'ImpliedResolver<any, GNonNull<GScalarType<string, string>>, unknown>'.
},
});

This is telling us that we need to provide a resolve function for the nameBackwards field. The resolve function recieves the source type that we provided when creating the object type. This allows us to calculate the value of the field based on the source type.

const
const User: GObjectType<UserSource, unknown>
User
=
const g: GWithContext<unknown>
g
.
object: <UserSource>(youOnlyNeedToPassATypeParameterToThisFunctionYouPassTheActualRuntimeArgsOnTheResultOfThisFunction?: {
youOnlyNeedToPassATypeParameterToThisFunctionYouPassTheActualRuntimeArgsOnTheResultOfThisFunction: true;
}) => <Fields, Interfaces>(config: {
...;
} & Omit<...>) => GObjectType<...>
object
<
type UserSource = {
id: string;
name: string;
}
UserSource
>()({
name: string
name
: "User",
fields: {
id: GField<UserSource, any, GNonNull<GScalarType<string, string>>, ImpliedResolver<any, GNonNull<GScalarType<string, string>>, unknown>, unknown>;
name: GField<...>;
nameBackwards: GField<...>;
} | (() => {
id: GField<UserSource, any, GNonNull<GScalarType<string, string>>, ImpliedResolver<any, GNonNull<GScalarType<string, string>>, unknown>, unknown>;
name: GField<...>;
nameBackwards: GField<...>;
})
fields
: {
id: GField<UserSource, any, GNonNull<GScalarType<string, string>>, ImpliedResolver<any, GNonNull<GScalarType<string, string>>, unknown>, unknown>
id
:
const g: GWithContext<unknown>
g
.
field: <UserSource, GNonNull<GScalarType<string, string>>, unknown, any>(field: FieldFuncArgs<UserSource, any, GNonNull<GScalarType<string, string>>, unknown> & {
...;
}) => GField<...>
field
({
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 ID: GScalarType<string, string>
ID
) }),
name: GField<UserSource, any, GNonNull<GScalarType<string, string>>, ImpliedResolver<any, GNonNull<GScalarType<string, string>>, unknown>, unknown>
name
:
const g: GWithContext<unknown>
g
.
field: <UserSource, GNonNull<GScalarType<string, string>>, unknown, any>(field: FieldFuncArgs<UserSource, any, GNonNull<GScalarType<string, string>>, unknown> & {
...;
}) => GField<...>
field
({
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
) }),
nameBackwards: GField<UserSource, any, GNonNull<GScalarType<string, string>>, unknown, unknown>
nameBackwards
:
const g: GWithContext<unknown>
g
.
field: <UserSource, GNonNull<GScalarType<string, string>>, (source: UserSource) => string, any>(field: FieldFuncArgs<UserSource, any, GNonNull<...>, unknown> & {
...;
}) => GField<...>
field
({
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
),
resolve: ((source: UserSource, args: {}, context: unknown, info: GraphQLResolveInfo) => InferValueFromOutputType<GNonNull<GScalarType<string, string>>>) & ((source: UserSource) => string)
resolve
(
source: UserSource
source
) {
return
source: UserSource
source
.
name: string
name
.
String.split(separator: string | RegExp, limit?: number): string[] (+1 overload)
split
("").
Array<string>.reverse(): string[]
reverse
().
Array<string>.join(separator?: string): string
join
("");
},
}),
},
});

Field Arguments

Fields can also have arguments. Arguments are defined using the args object on the field definition. The args object is a map of argument names to argument definitions. The argument definitions are created using the g.arg function. @graphql-ts/schema will then infer the second parameter to resolve based on the args defintion.

const
const User: GObjectType<UserSource, unknown>
User
=
const g: GWithContext<unknown>
g
.
object: <UserSource>(youOnlyNeedToPassATypeParameterToThisFunctionYouPassTheActualRuntimeArgsOnTheResultOfThisFunction?: {
youOnlyNeedToPassATypeParameterToThisFunctionYouPassTheActualRuntimeArgsOnTheResultOfThisFunction: true;
}) => <Fields, Interfaces>(config: {
...;
} & Omit<...>) => GObjectType<...>
object
<
type UserSource = {
id: string;
name: string;
}
UserSource
>()({
name: string
name
: "User",
fields: {
id: GField<UserSource, any, GNonNull<GScalarType<string, string>>, ImpliedResolver<any, GNonNull<GScalarType<string, string>>, unknown>, unknown>;
name: GField<...>;
nameWithLength: GField<...>;
} | (() => {
id: GField<UserSource, any, GNonNull<GScalarType<string, string>>, ImpliedResolver<any, GNonNull<GScalarType<string, string>>, unknown>, unknown>;
name: GField<...>;
nameWithLength: GField<...>;
})
fields
: {
id: GField<UserSource, any, GNonNull<GScalarType<string, string>>, ImpliedResolver<any, GNonNull<GScalarType<string, string>>, unknown>, unknown>
id
:
const g: GWithContext<unknown>
g
.
field: <UserSource, GNonNull<GScalarType<string, string>>, unknown, any>(field: FieldFuncArgs<UserSource, any, GNonNull<GScalarType<string, string>>, unknown> & {
...;
}) => GField<...>
field
({
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 ID: GScalarType<string, string>
ID
) }),
name: GField<UserSource, any, GNonNull<GScalarType<string, string>>, ImpliedResolver<any, GNonNull<GScalarType<string, string>>, unknown>, unknown>
name
:
const g: GWithContext<unknown>
g
.
field: <UserSource, GNonNull<GScalarType<string, string>>, unknown, any>(field: FieldFuncArgs<UserSource, any, GNonNull<GScalarType<string, string>>, unknown> & {
...;
}) => GField<...>
field
({
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
) }),
nameWithLength: GField<UserSource, {
length: GArg<GNonNull<GScalarType<number, number>>, false>;
}, GNonNull<GScalarType<string, string>>, unknown, unknown>
nameWithLength
:
const g: GWithContext<unknown>
g
.
field: <UserSource, GNonNull<GScalarType<string, string>>, (source: UserSource, args: {
readonly length: number;
}) => string, {
length: GArg<...>;
}>(field: FieldFuncArgs<...> & {
...;
}) => GField<...>
field
({
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
),
args?: {
length: GArg<GNonNull<GScalarType<number, number>>, false>;
}
args
: {
length: GArg<GNonNull<GScalarType<number, number>>, false>
length
:
const g: GWithContext<unknown>
g
.
arg: <GNonNull<GScalarType<number, number>>, undefined>(arg: {
type: GNonNull<GScalarType<number, number>>;
description?: Maybe<string>;
extensions?: (Readonly<...> & Readonly<...>) | ... 1 more ... | undefined;
astNode?: Maybe<...>;
deprecationReason?: Maybe<...>;
} & {
...;
}) => GArg<...>
arg
({
type: GNonNull<GScalarType<number, number>>
type
:
const g: GWithContext<unknown>
g
.
nonNull: <GScalarType<number, number>>(of: GScalarType<number, number>) => GNonNull<GScalarType<number, number>>
nonNull
(
const g: GWithContext<unknown>
g
.
type Int: GScalarType<number, number>
Int
) }),
},
resolve: ((source: UserSource, args: {
readonly length: number;
}, context: unknown, info: GraphQLResolveInfo) => InferValueFromOutputType<GNonNull<GScalarType<string, string>>>) & ((source: UserSource, args: {
...;
}) => string)
resolve
(
source: UserSource
source
,
args: {
readonly length: number;
}
args
) {
return
source: UserSource
source
.
name: string
name
.
String.slice(start?: number, end?: number): string
slice
(0,
args: {
readonly length: number;
}
args
.l );
length
},
}),
},
});

Context

The resolve function is also provided a third argument, the context. This is useful for providing things like database connections, authentication information, etc. The context is defined by the Context type that is passed to gWithContext.

import {
function gWithContext<Context>(): GWithContext<Context>
gWithContext
} from "@graphql-ts/schema";
type
type Context = {
loadUser: (id: string) => Promise<UserSource | null>;
}
Context
= {
loadUser: (id: string) => Promise<UserSource | null>
loadUser
: (
id: string
id
: string) =>
interface Promise<T>
Promise
<
type UserSource = {
id: string;
name: string;
}
UserSource
| null>;
};
const
const g: GWithContext<Context>
g
=
gWithContext<Context>(): GWithContext<Context>
gWithContext
<
type Context = {
loadUser: (id: string) => Promise<UserSource | null>;
}
Context
>
();
type
type g<T> = T extends () => (args: any) => infer R ? R : T extends (args: any) => infer R ? R : never
g
<
function (type parameter) T in type g<T>
T
> =
(alias) namespace gWithContext
import gWithContext
gWithContext
.
type gWithContext.infer<T> = T extends () => (args: any) => infer R ? R : T extends (args: any) => infer R ? R : never
infer
<
function (type parameter) T in type g<T>
T
>;
const
const Query: GObjectType<unknown, Context>
Query
=
const g: GWithContext<Context>
g
.
object: <unknown>(youOnlyNeedToPassATypeParameterToThisFunctionYouPassTheActualRuntimeArgsOnTheResultOfThisFunction?: {
youOnlyNeedToPassATypeParameterToThisFunctionYouPassTheActualRuntimeArgsOnTheResultOfThisFunction: true;
}) => <Fields, Interfaces>(config: {
...;
} & Omit<...>) => GObjectType<...>
object
()({
name: string
name
: "Query",
fields: {
user: GField<unknown, {
id: GArg<GNonNull<GScalarType<string, string>>, false>;
}, GObjectType<UserSource, Context>, unknown, Context>;
} | (() => {
user: GField<unknown, {
id: GArg<GNonNull<GScalarType<string, string>>, false>;
}, GObjectType<UserSource, Context>, unknown, Context>;
})
fields
: () => ({
user: GField<unknown, {
id: GArg<GNonNull<GScalarType<string, string>>, false>;
}, GObjectType<UserSource, Context>, unknown, Context>
user
:
const g: GWithContext<Context>
g
.
field: <unknown, GObjectType<UserSource, Context>, (_: unknown, args: {
readonly id: string;
}, context: Context) => any, {
id: GArg<GNonNull<GScalarType<string, string>>, false>;
}>(field: FieldFuncArgs<...> & {
...;
}) => GField<...>
field
({
type: GObjectType<UserSource, Context>
type
:
const User: GObjectType<UserSource, Context>
User
,
args?: {
id: GArg<GNonNull<GScalarType<string, string>>, false>;
}
args
: {
id: GArg<GNonNull<GScalarType<string, string>>, false>
id
:
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 ID: GScalarType<string, string>
ID
) }),
},
resolve: ((source: unknown, args: {
readonly id: string;
}, context: Context, info: GraphQLResolveInfo) => InferValueFromOutputType<GObjectType<UserSource, Context>>) & ((_: unknown, args: {
...;
}, context: Context) => any)
resolve
(
_: unknown
_
,
args: {
readonly id: string;
}
args
,
context: Context
context
) {
return
context: Context
context
.lo
any
loadUser
},
}),
}),
});

Circular Types

Since GraphQL, like the name suggests, is about querying a graph, it’s common to have circular types in your schema where one type references another type that references the first type. To start with, we need to make fields a function that returns a function so we can lazily reference the User type:

const User =
const g: GWithContext<unknown>
g
.
object: <UserSource>(youOnlyNeedToPassATypeParameterToThisFunctionYouPassTheActualRuntimeArgsOnTheResultOfThisFunction?: {
youOnlyNeedToPassATypeParameterToThisFunctionYouPassTheActualRuntimeArgsOnTheResultOfThisFunction: true;
}) => <Fields, Interfaces>(config: {
...;
} & Omit<...>) => GObjectType<...>
object
<
type UserSource = {
id: string;
name: string;
}
UserSource
>()({
Error ts(7022) ― 'User' 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
: "User",
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.
id: GField<UserSource, any, GNonNull<GScalarType<string, string>>, ImpliedResolver<any, GNonNull<GScalarType<string, string>>, unknown>, unknown>
id
:
const g: GWithContext<unknown>
g
.
field: <UserSource, GNonNull<GScalarType<string, string>>, unknown, any>(field: FieldFuncArgs<UserSource, any, GNonNull<GScalarType<string, string>>, unknown> & {
...;
}) => GField<...>
field
({
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 ID: GScalarType<string, string>
ID
) }),
name: GField<UserSource, any, GNonNull<GScalarType<string, string>>, ImpliedResolver<any, GNonNull<GScalarType<string, string>>, unknown>, unknown>
name
:
const g: GWithContext<unknown>
g
.
field: <UserSource, GNonNull<GScalarType<string, string>>, unknown, any>(field: FieldFuncArgs<UserSource, any, GNonNull<GScalarType<string, string>>, unknown> & {
...;
}) => GField<...>
field
({
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: GField<UserSource, any, GList<any>, unknown, unknown>
friends
:
const g: GWithContext<unknown>
g
.
field: <UserSource, GList<any>, () => never[], any>(field: FieldFuncArgs<UserSource, any, GList<any>, unknown> & {
resolve: ((source: UserSource, args: {}, context: unknown, info: GraphQLResolveInfo) => InferValueFromOutputType<...>) & (() => never[]);
}) => GField<...>
field
({
type: GList<any>
type
:
const g: GWithContext<unknown>
g
.
list: <any>(of: any) => GList<any>
list
(
const User: any
User
),
resolve: ((source: UserSource, args: {}, context: unknown, info: GraphQLResolveInfo) => InferValueFromOutputType<GList<any>>) & (() => never[])
resolve
: () => [],
}),
}),
});

TypeScript doesn’t understand this circularity though, we can fix this by using the g type and the g.object function to be explicit about the type of User:

import {
function gWithContext<Context>(): GWithContext<Context>
gWithContext
} from "@graphql-ts/schema";
const
const g: GWithContext<unknown>
g
=
gWithContext<unknown>(): GWithContext<unknown>
gWithContext
();
type
type g<T> = T extends () => (args: any) => infer R ? R : T extends (args: any) => infer R ? R : never
g
<
function (type parameter) T in type g<T>
T
> =
(alias) namespace gWithContext
import gWithContext
gWithContext
.
type gWithContext.infer<T> = T extends () => (args: any) => infer R ? R : T extends (args: any) => infer R ? R : never
infer
<
function (type parameter) T in type g<T>
T
>;
type
type UserSource = {
id: string;
name: string;
}
UserSource
= {
id: string
id
: string;
name: string
name
: string };
const
const User: GObjectType<UserSource, unknown>
User
:
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
.
object: <Source>(youOnlyNeedToPassATypeParameterToThisFunctionYouPassTheActualRuntimeArgsOnTheResultOfThisFunction?: {
youOnlyNeedToPassATypeParameterToThisFunctionYouPassTheActualRuntimeArgsOnTheResultOfThisFunction: true;
}) => <Fields extends { [Key in keyof Fields]: GField<...>; } & InterfaceFieldsToOutputFields<...>, const Interfaces extends readonly GInterfaceType<...>[] = []>(config: {
...;
} & Omit<...>) => GObjectType<...>
object
<
type UserSource = {
id: string;
name: string;
}
UserSource
>>
=
const g: GWithContext<unknown>
g
.
object: <UserSource>(youOnlyNeedToPassATypeParameterToThisFunctionYouPassTheActualRuntimeArgsOnTheResultOfThisFunction?: {
youOnlyNeedToPassATypeParameterToThisFunctionYouPassTheActualRuntimeArgsOnTheResultOfThisFunction: true;
}) => <Fields, Interfaces>(config: {
...;
} & Omit<...>) => GObjectType<...>
object
<
type UserSource = {
id: string;
name: string;
}
UserSource
>()({
name: string
name
: "User",
fields: {
id: GField<UserSource, any, GNonNull<GScalarType<string, string>>, ImpliedResolver<any, GNonNull<GScalarType<string, string>>, unknown>, unknown>;
name: GField<...>;
friends: GField<...>;
} | (() => {
id: GField<UserSource, any, GNonNull<GScalarType<string, string>>, ImpliedResolver<any, GNonNull<GScalarType<string, string>>, unknown>, unknown>;
name: GField<...>;
friends: GField<...>;
})
fields
: () => ({
id: GField<UserSource, any, GNonNull<GScalarType<string, string>>, ImpliedResolver<any, GNonNull<GScalarType<string, string>>, unknown>, unknown>
id
:
const g: GWithContext<unknown>
g
.
field: <UserSource, GNonNull<GScalarType<string, string>>, unknown, any>(field: FieldFuncArgs<UserSource, any, GNonNull<GScalarType<string, string>>, unknown> & {
...;
}) => GField<...>
field
({
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 ID: GScalarType<string, string>
ID
) }),
name: GField<UserSource, any, GNonNull<GScalarType<string, string>>, ImpliedResolver<any, GNonNull<GScalarType<string, string>>, unknown>, unknown>
name
:
const g: GWithContext<unknown>
g
.
field: <UserSource, GNonNull<GScalarType<string, string>>, unknown, any>(field: FieldFuncArgs<UserSource, any, GNonNull<GScalarType<string, string>>, unknown> & {
...;
}) => GField<...>
field
({
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: GField<UserSource, any, GList<GObjectType<UserSource, unknown>>, unknown, unknown>
friends
:
const g: GWithContext<unknown>
g
.
field: <UserSource, GList<GObjectType<UserSource, unknown>>, () => never[], any>(field: FieldFuncArgs<UserSource, any, GList<GObjectType<UserSource, unknown>>, unknown> & {
...;
}) => GField<...>
field
({
type: GList<GObjectType<UserSource, unknown>>
type
:
const g: GWithContext<unknown>
g
.
list: <GObjectType<UserSource, unknown>>(of: GObjectType<UserSource, unknown>) => GList<GObjectType<UserSource, unknown>>
list
(
const User: GObjectType<UserSource, unknown>
User
),
resolve: ((source: UserSource, args: {}, context: unknown, info: GraphQLResolveInfo) => InferValueFromOutputType<GList<GObjectType<UserSource, unknown>>>) & (() => never[])
resolve
: () => [],
}),
}),
});
Alternative Syntax

The g type and g.object function is a shorthand for using GObjectType. You can also use GObjectType directly, though it does mean importing the extra type and instead of only providing the source type, you also need to provide the context type whereas with g<typeof g.object<UserSource>>, the context type is inferred from the gWithContext call.

import {
function gWithContext<Context>(): GWithContext<Context>
gWithContext
,
class GObjectType<Source, Context>
GObjectType
} from "@graphql-ts/schema";
type
type Context = {}
Context
= {};
const
const g: GWithContext<Context>
g
=
gWithContext<Context>(): GWithContext<Context>
gWithContext
<
type Context = {}
Context
>();
type
type g<T> = T extends () => (args: any) => infer R ? R : T extends (args: any) => infer R ? R : never
g
<
function (type parameter) T in type g<T>
T
> =
(alias) namespace gWithContext
import gWithContext
gWithContext
.
type gWithContext.infer<T> = T extends () => (args: any) => infer R ? R : T extends (args: any) => infer R ? R : never
infer
<
function (type parameter) T in type g<T>
T
>;
type
type UserSource = {
id: string;
name: string;
}
UserSource
= {
id: string
id
: string;
name: string
name
: string;
};
const
const User: GObjectType<UserSource, Context>
User
:
class GObjectType<Source, Context>
GObjectType
<
type UserSource = {
id: string;
name: string;
}
UserSource
,
type Context = {}
Context
>
=
const g: GWithContext<Context>
g
.
object: <UserSource>(youOnlyNeedToPassATypeParameterToThisFunctionYouPassTheActualRuntimeArgsOnTheResultOfThisFunction?: {
youOnlyNeedToPassATypeParameterToThisFunctionYouPassTheActualRuntimeArgsOnTheResultOfThisFunction: true;
}) => <Fields, Interfaces>(config: {
...;
} & Omit<...>) => GObjectType<...>
object
<
type UserSource = {
id: string;
name: string;
}
UserSource
>()({
name: string
name
: "User",
fields: {
id: GField<UserSource, any, GNonNull<GScalarType<string, string>>, ImpliedResolver<any, GNonNull<GScalarType<string, string>>, Context>, Context>;
name: GField<...>;
friends: GField<...>;
} | (() => {
id: GField<UserSource, any, GNonNull<GScalarType<string, string>>, ImpliedResolver<any, GNonNull<GScalarType<string, string>>, Context>, Context>;
name: GField<...>;
friends: GField<...>;
})
fields
: () => ({
id: GField<UserSource, any, GNonNull<GScalarType<string, string>>, ImpliedResolver<any, GNonNull<GScalarType<string, string>>, Context>, Context>
id
:
const g: GWithContext<Context>
g
.
field: <UserSource, GNonNull<GScalarType<string, string>>, unknown, any>(field: FieldFuncArgs<UserSource, any, GNonNull<GScalarType<string, string>>, Context> & {
...;
}) => GField<...>
field
({
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 ID: GScalarType<string, string>
ID
) }),
name: GField<UserSource, any, GNonNull<GScalarType<string, string>>, ImpliedResolver<any, GNonNull<GScalarType<string, string>>, Context>, Context>
name
:
const g: GWithContext<Context>
g
.
field: <UserSource, GNonNull<GScalarType<string, string>>, unknown, any>(field: FieldFuncArgs<UserSource, any, GNonNull<GScalarType<string, string>>, Context> & {
...;
}) => GField<...>
field
({
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
) }),
friends: GField<UserSource, any, GList<GObjectType<UserSource, Context>>, unknown, Context>
friends
:
const g: GWithContext<Context>
g
.
field: <UserSource, GList<GObjectType<UserSource, Context>>, () => never[], any>(field: FieldFuncArgs<UserSource, any, GList<GObjectType<UserSource, Context>>, Context> & {
...;
}) => GField<...>
field
({
type: GList<GObjectType<UserSource, Context>>
type
:
const g: GWithContext<Context>
g
.
list: <GObjectType<UserSource, Context>>(of: GObjectType<UserSource, Context>) => GList<GObjectType<UserSource, Context>>
list
(
const User: GObjectType<UserSource, Context>
User
),
resolve: ((source: UserSource, args: {}, context: Context, info: GraphQLResolveInfo) => InferValueFromOutputType<GList<GObjectType<UserSource, Context>>>) & (() => never[])
resolve
: () => [],
}),
}),
});