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) }), },});
type User { id: ID! name: 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 User { id: ID! name: String! nameBackwards: String!}
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(""); }, }), },});
type User { id: ID! name: String! nameBackwards: String!}
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 }, }), },});
type User { id: ID! name: String! nameWithLength(length: Int!): String!}
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 gWithContextimport 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 }, }), }),});
type Query { user(id: ID!): User}
type User { id: ID! name: String!}
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) ― name: string
name: "User", fields: () => ({Error ts(7023) ― 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 gWithContextimport 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: () => [], }), }),});
type User { id: ID! name: String! friends: [User]}
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 gWithContextimport 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: () => [], }), }),});
type User { id: ID! name: String! friends: [User]}