如何为Apollo GraphQL子图的Resolver Context设置类型?
Apollo GraphQL子图Resolver Context类型配置方案
问题描述
我有一个简单的Apollo GraphQL子图,想要为Resolver中的context参数设置类型。编写的代码如下:
interface Context { dataSources: { shopify: Shopify; } } const server = new ApolloServer({ schema: buildSubgraphSchema({ typeDefs, resolvers: { Query: { shop(_, _args, ctx: Context) { console.log("ctx:", ctx) }, } } }), dataSources: () => ({ shopify: new Shopify() }) });
但自定义的Context接口与Resolver预期类型不兼容,抛出TypeScript错误:
Argument of type '{ typeDefs: any; resolvers: { Query: { shop(_: any, _args: any, ctx: Context): void; }; }; }' is not assignable to parameter of type 'DocumentNode | (GraphQLSchemaModule | DocumentNode)[] | LegacySchemaModule'. Types of property 'resolvers' are incompatible. Property 'Query' is incompatible with index signature. Type '{ shop(_: any, _args: any, ctx: Context): void; }' is not assignable to type 'GraphQLScalarType<unknown, unknown> | { [enumValue: string]: string | number; } | { [fieldName: string]: GraphQLFieldResolver<any, unknown, any, unknown> | { requires?: string | undefined; resolve: GraphQLFieldResolver<...>; }; }'. Types of property 'shop' are incompatible. Type '(_: any, _args: any, ctx: Context) => void' is not assignable to type 'string | number | GraphQLFieldResolver<any, unknown, any, unknown> | { requires?: string | undefined; resolve: GraphQLFieldResolver<any, unknown, any, unknown>; } | undefined'. Type '(_: any, _args: any, ctx: Context) => void' is not assignable to type 'GraphQLFieldResolver<any, unknown, any, unknown>'. Types of parameters 'ctx' and 'context' are incompatible. Type 'unknown' is not assignable to type 'Context'.ts(2345)
需要知道如何正确设置Context类型,以正常访问接口及数据源。
解决方案
核心是通过泛型参数将自定义Context类型绑定到buildSubgraphSchema和Resolver上,让TypeScript正确识别上下文类型,而非仅在参数上标注类型。
方法一:单个Resolver类型断言
- 导入所需类型
import { buildSubgraphSchema, GraphQLFieldResolver } from '@apollo/subgraph';
- 绑定Context类型到Resolver
interface Context { dataSources: { shopify: Shopify; } } const resolvers = { Query: { // 使用as断言指定Resolver的上下文类型为Context shop: ((_, _args, ctx) => { console.log("ctx:", ctx); // 可直接访问ctx.dataSources.shopify return ctx.dataSources.shopify.getShop(); }) as GraphQLFieldResolver<any, Context, any>, }, }; const server = new ApolloServer({ // 给buildSubgraphSchema传入泛型参数<Context> schema: buildSubgraphSchema<Context>({ typeDefs, resolvers }), dataSources: () => ({ shopify: new Shopify() }), });
方法二:全局Resolver类型映射(推荐)
如果存在多个Resolver,可定义统一的Resolver类型映射,避免重复断言:
import { buildSubgraphSchema, GraphQLFieldResolver } from '@apollo/subgraph'; interface Context { dataSources: { shopify: Shopify; } } // 定义全局Resolver类型,绑定Context type AppResolvers = { Query: { shop: GraphQLFieldResolver<any, Context, any>; // 可添加其他Query字段 }; // 可添加Mutation、自定义类型的Resolver }; // 使用定义好的AppResolvers类型,ctx自动推断为Context const resolvers: AppResolvers = { Query: { shop(_, _args, ctx) { console.log("ctx:", ctx); return ctx.dataSources.shopify.getShop(); }, }, }; const server = new ApolloServer({ schema: buildSubgraphSchema<Context>({ typeDefs, resolvers }), dataSources: () => ({ shopify: new Shopify() }), });
错误原因说明
buildSubgraphSchema默认将上下文类型推断为unknown,而直接在Resolver参数标注Context会导致类型不匹配。通过给buildSubgraphSchema传入泛型<Context>,可让整个Schema的Resolver上下文类型统一为自定义接口,结合GraphQLFieldResolver泛型,TypeScript就能正确识别Resolver参数的类型。
内容的提问来源于stack exchange,提问作者Stretch0
相关产品推荐
相关产品推荐

