GraphQL Code Generator plugin for generating TypeScript types for resolvers signature
npx @tessl/cli install tessl/npm-graphql-codegen--typescript-resolvers@4.5.0GraphQL Code Generator plugin that generates TypeScript signatures for GraphQL resolver functions, providing type safety and consistency between GraphQL schema definitions and their corresponding TypeScript implementations. It analyzes GraphQL schemas and generates strongly-typed resolver interfaces that include proper typing for arguments, context, return types, and GraphQL resolve info.
npm install @graphql-codegen/typescript-resolversgraphql, @graphql-codegen/cligraphql-sock (for semantic non-null custom directives)import { plugin } from "@graphql-codegen/typescript-resolvers";For CommonJS:
const { plugin } = require("@graphql-codegen/typescript-resolvers");For configuration types and visitor class:
import {
TypeScriptResolversPluginConfig,
TypeScriptResolversVisitor
} from "@graphql-codegen/typescript-resolvers";This plugin is used as part of GraphQL Code Generator configuration to generate TypeScript resolver signatures:
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
schema: 'path/to/schema.graphql',
generates: {
'src/generated/resolvers-types.ts': {
plugins: ['typescript', 'typescript-resolvers'],
config: {
contextType: './context#Context',
mappers: {
User: './models#UserModel'
}
}
}
}
};
export default config;The plugin consists of several key components:
Main plugin function that generates TypeScript resolver signatures from GraphQL schemas.
function plugin(
schema: GraphQLSchema,
documents: Types.DocumentFile[],
config: TypeScriptResolversPluginConfig
): Promise<Types.ComplexPluginOutput<{
generatedResolverTypes: RootResolver['generatedResolverTypes'];
}>>;Comprehensive configuration options for customizing resolver generation behavior, including type mappings, custom resolvers, and output formatting.
interface TypeScriptResolversPluginConfig extends RawResolversConfig {
useIndexSignature?: boolean;
noSchemaStitching?: boolean;
wrapFieldDefinitions?: boolean;
customResolveInfo?: string;
customResolverFn?: string;
directiveResolverMappings?: Record<string, string>;
allowParentTypeOverride?: boolean;
optionalInfoArgument?: boolean;
makeResolverTypeCallable?: boolean;
}Advanced visitor class that handles AST traversal and generates TypeScript code with proper type safety and customization.
class TypeScriptResolversVisitor extends BaseResolversVisitor<
TypeScriptResolversPluginConfig,
ParsedTypeScriptResolversConfig
> {
constructor(pluginConfig: TypeScriptResolversPluginConfig, schema: GraphQLSchema);
transformParentGenericType(parentType: string): string;
formatRootResolver(schemaTypeName: string, resolverType: string, declarationKind: DeclarationKind): string;
ListType(node: ListTypeNode): string;
NamedType(node: NamedTypeNode): string;
NonNullType(node: NonNullTypeNode): string;
buildEnumResolverContentBlock(node: EnumTypeDefinitionNode, mappedEnumType: string): string;
}The plugin generates comprehensive TypeScript type definitions for resolvers:
// Basic resolver function signature
type ResolverFn<TResult, TParent, TContext, TArgs> = (
parent: TParent,
args: TArgs,
context: TContext,
info: GraphQLResolveInfo
) => Promise<TResult> | TResult;
// Resolver type (union of all resolver variants)
type Resolver<TResult, TParent = {}, TContext = {}, TArgs = {}> =
| ResolverFn<TResult, TParent, TContext, TArgs>
| ResolverWithResolve<TResult, TParent, TContext, TArgs>;
// Root resolvers object
type Resolvers<ContextType = any> = ResolversObject<{
Query?: QueryResolvers<ContextType>;
Mutation?: MutationResolvers<ContextType>;
Subscription?: SubscriptionResolvers<ContextType>;
// ... generated types for each GraphQL type
}>;type SubscriptionSubscribeFn<TResult, TParent, TContext, TArgs> = (
parent: TParent,
args: TArgs,
context: TContext,
info: GraphQLResolveInfo
) => AsyncIterable<TResult> | Promise<AsyncIterable<TResult>>;
type SubscriptionResolveFn<TResult, TParent, TContext, TArgs> = (
parent: TParent,
args: TArgs,
context: TContext,
info: GraphQLResolveInfo
) => TResult | Promise<TResult>;
interface SubscriptionSubscriberObject<TResult, TKey extends string, TParent, TContext, TArgs> {
subscribe: SubscriptionSubscribeFn<{ [key in TKey]: TResult }, TParent, TContext, TArgs>;
resolve?: SubscriptionResolveFn<TResult, { [key in TKey]: TResult }, TContext, TArgs>;
}// Type resolver for unions/interfaces
type TypeResolveFn<TTypes, TParent = {}, TContext = {}> = (
parent: TParent,
context: TContext,
info: GraphQLResolveInfo
) => Maybe<TTypes> | Promise<Maybe<TTypes>>;
// Type guard function
type IsTypeOfResolverFn<T = {}, TContext = {}> = (
obj: T,
context: TContext,
info: GraphQLResolveInfo
) => boolean | Promise<boolean>;
// Directive resolver function
type DirectiveResolverFn<TResult = {}, TParent = {}, TContext = {}, TArgs = {}> = (
next: NextResolverFn<TResult>,
parent: TParent,
args: TArgs,
context: TContext,
info: GraphQLResolveInfo
) => TResult | Promise<TResult>;
// Enum resolver signature
type EnumResolverSignature<T, AllowedValues = any> = {
[key in keyof T]?: AllowedValues
};