GraphQL Code Generator plugin for generating TypeScript types for resolvers signature
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
The TypeScript Resolvers plugin provides extensive configuration options to customize resolver generation behavior, type mappings, and output formatting.
Complete configuration interface extending the base resolvers configuration.
/**
* Configuration options for the TypeScript Resolvers GraphQL Code Generator plugin
* Extends RawResolversConfig with TypeScript-specific options
*/
interface TypeScriptResolversPluginConfig extends RawResolversConfig {
useIndexSignature?: boolean;
noSchemaStitching?: boolean;
wrapFieldDefinitions?: boolean;
customResolveInfo?: string;
customResolverFn?: string;
directiveResolverMappings?: Record<string, string>;
allowParentTypeOverride?: boolean;
optionalInfoArgument?: boolean;
makeResolverTypeCallable?: boolean;
}Controls whether to add index signatures to generated resolver objects.
/**
* Adds an index signature to any generated resolver
* @default false
*/
useIndexSignature?: boolean;Usage Example:
// codegen.ts
const config: CodegenConfig = {
generates: {
'resolvers-types.ts': {
plugins: ['typescript', 'typescript-resolvers'],
config: {
useIndexSignature: true
}
}
}
};
// Generated output with useIndexSignature: true
export type WithIndex<TObject> = TObject & Record<string, any>;
export type ResolversObject<TObject> = WithIndex<TObject>;
export type Resolvers<ContextType = any> = ResolversObject<{
Query?: QueryResolvers<ContextType>;
User?: UserResolvers<ContextType>;
}>;Controls schema stitching support in resolver signatures.
/**
* Disables/Enables Schema Stitching support
* By default, resolver signatures do not include schema-stitching support
* Set to false to enable schema stitching resolver types
* @default true
*/
noSchemaStitching?: boolean;Usage Example:
// Enable schema stitching support
const config: CodegenConfig = {
generates: {
'resolvers-types.ts': {
plugins: ['typescript', 'typescript-resolvers'],
config: {
noSchemaStitching: false
}
}
}
};
// Generated additional types when noSchemaStitching: false
export type LegacyStitchingResolver<TResult, TParent, TContext, TArgs> = {
fragment: string;
resolve: ResolverFn<TResult, TParent, TContext, TArgs>;
};
export type NewStitchingResolver<TResult, TParent, TContext, TArgs> = {
selectionSet: string | ((fieldNode: FieldNode) => SelectionSetNode);
resolve: ResolverFn<TResult, TParent, TContext, TArgs>;
};
export type StitchingResolver<TResult, TParent, TContext, TArgs> =
| LegacyStitchingResolver<TResult, TParent, TContext, TArgs>
| NewStitchingResolver<TResult, TParent, TContext, TArgs>;Controls wrapping of field definitions for Federation compatibility.
/**
* Set to true to wrap field definitions with FieldWrapper
* Useful for compatibility with federation: true when allowing
* return types such as Promises and functions
* @default false
*/
wrapFieldDefinitions?: boolean;Allows providing a custom GraphQLResolveInfo type.
/**
* Provide custom GraphQLResolveInfo type instead of default from graphql-js
* @default "graphql#GraphQLResolveInfo"
*/
customResolveInfo?: string;Usage Example:
const config: CodegenConfig = {
generates: {
'resolvers-types.ts': {
plugins: ['typescript', 'typescript-resolvers'],
config: {
customResolveInfo: './types#CustomResolveInfo'
}
}
}
};
// Uses CustomResolveInfo instead of GraphQLResolveInfo in resolver signaturesAllows providing a custom resolver function signature.
/**
* Provide custom resolver function type that uses generics <TResult, TParent, TContext, TArgs>
* @default "(parent: TParent, args: TArgs, context: TContext, info: GraphQLResolveInfo) => Promise<TResult> | TResult"
*/
customResolverFn?: string;Usage Examples:
// Custom resolver function from external file
const config: CodegenConfig = {
generates: {
'resolvers-types.ts': {
plugins: ['typescript', 'typescript-resolvers'],
config: {
customResolverFn: './resolver-types#CustomResolverFn'
}
}
}
};
// Inline custom resolver function (useful for Graphile integration)
const graphileConfig: CodegenConfig = {
generates: {
'resolvers-types.ts': {
plugins: [
{
add: {
content: "import { GraphileHelpers } from 'graphile-utils/node8plus/fieldHelpers';"
}
},
'typescript',
'typescript-resolvers'
],
config: {
customResolverFn: `(
parent: TParent,
args: TArgs,
context: TContext,
info: GraphQLResolveInfo & { graphile: GraphileHelpers<TParent> }
) => Promise<TResult> | TResult;`
}
}
}
};Maps GraphQL directives to specific resolver types.
/**
* Map directive usage to specific resolver types
* Key: directive name, Value: resolver type mapper
*/
directiveResolverMappings?: Record<string, string>;Usage Example:
const config: CodegenConfig = {
generates: {
'resolvers-types.ts': {
plugins: ['typescript', 'typescript-resolvers'],
config: {
customResolverFn: '../resolver-types.ts#UnauthenticatedResolver',
directiveResolverMappings: {
authenticated: '../resolver-types.ts#AuthenticatedResolver',
admin: '../resolver-types.ts#AdminResolver'
}
}
}
}
};
// Schema with directives
// type Query {
// publicData: String
// userData: String @authenticated
// adminData: String @admin
// }
// Generated resolver types will use specific resolver types based on directivesControls parent type generic constraints in resolver signatures.
/**
* Override ParentType generic in each resolver by avoiding base type enforcement
* Generates "ParentType = Type" instead of "ParentType extends Type = Type"
* @default false
*/
allowParentTypeOverride?: boolean;Usage Example:
// With allowParentTypeOverride: false (default)
export type UserResolvers<
ContextType = any,
ParentType extends ResolversParentTypes['User'] = ResolversParentTypes['User']
> = { ... };
// With allowParentTypeOverride: true
export type UserResolvers<
ContextType = any,
ParentType = ResolversParentTypes['User']
> = { ... };Makes the GraphQL info argument optional in resolver signatures.
/**
* Sets info argument of resolver function to be optional
* Useful for testing scenarios where info parameter is not needed
* @default false
*/
optionalInfoArgument?: boolean;Usage Example:
// With optionalInfoArgument: false (default)
export type ResolverFn<TResult, TParent, TContext, TArgs> = (
parent: TParent,
args: TArgs,
context: TContext,
info: GraphQLResolveInfo
) => Promise<TResult> | TResult;
// With optionalInfoArgument: true
export type ResolverFn<TResult, TParent, TContext, TArgs> = (
parent: TParent,
args: TArgs,
context: TContext,
info?: GraphQLResolveInfo
) => Promise<TResult> | TResult;Controls whether the Resolver type should be callable.
/**
* Set to true to allow the Resolver type to be callable
* Changes resolver union type to only include the function signature
* @default false
*/
makeResolverTypeCallable?: boolean;Usage Example:
// With makeResolverTypeCallable: false (default)
export type Resolver<TResult, TParent = {}, TContext = {}, TArgs = {}> =
| ResolverFn<TResult, TParent, TContext, TArgs>
| ResolverWithResolve<TResult, TParent, TContext, TArgs>;
// With makeResolverTypeCallable: true
export type Resolver<TResult, TParent = {}, TContext = {}, TArgs = {}> =
ResolverFn<TResult, TParent, TContext, TArgs>;The TypeScriptResolversPluginConfig extends RawResolversConfig, inheriting all base resolver configuration options including:
contextType: Type for the GraphQL contextmappers: Custom type mappings for GraphQL typesfederation: Enable Apollo Federation supportscalars: Custom scalar type mappingsnamingConvention: Naming convention for generated typestypesPrefix: Prefix for generated type namestypesSuffix: Suffix for generated type namesComplete Configuration Example:
const config: CodegenConfig = {
schema: 'schema.graphql',
generates: {
'src/types/resolvers.ts': {
plugins: ['typescript', 'typescript-resolvers'],
config: {
// Base configuration
contextType: './context#GraphQLContext',
federation: true,
mappers: {
User: './models#UserModel',
Post: './models#PostModel'
},
scalars: {
DateTime: 'Date',
JSON: 'Record<string, any>'
},
// TypeScript-specific configuration
useIndexSignature: false,
noSchemaStitching: true,
wrapFieldDefinitions: false,
optionalInfoArgument: false,
makeResolverTypeCallable: false,
allowParentTypeOverride: false,
// Custom resolvers
customResolverFn: './types#CustomResolverFn',
directiveResolverMappings: {
auth: './types#AuthenticatedResolver'
}
}
}
}
};