繁体   English   中英

如何为 Apollo 解析器上下文设置类型?

[英]How to set type for Apollo resolver context?

我有一个简单的 Apollo GraphQL 子图,我想在其中为我的解析器中的上下文 arg 设置类型。

我创建了一个解析器并将上下文的类型设置如下:

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接口似乎与我的解析器期望的类型不兼容,我收到以下错误:

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)

如何为我的解析器设置上下文类型,以便我可以访问接口和数据源等?

好的,我想我找到了更好的解决方案。

首先让我们真正了解buildSubgraphSchema可以接受什么:

buildSubgraphSchema(
  modulesOrSDL:
    | (GraphQLSchemaModule | DocumentNode)[] //interesting...
    | DocumentNode
    | LegacySchemaModule, //our tried and true way
): GraphQLSchema

问题是我们试图传入一个LegacySchemaModule ( {typeDefs, resolvers} ) 但由于传入GraphQLResovlerMap<unknown>泛型与显式定义的Context产生了冲突

type LegacySchemaModule = {
  typeDefs: DocumentNode | DocumentNode[];
  resolvers?: GraphQLResolverMap<unknown>; //note `unknown`, the root of our typing errors
};

我们需要在解析器中实际作用于上下文的是一个GraphQLSchemaModule定义如下:

export interface GraphQLSchemaModule {
  typeDefs: DocumentNode;
  resolvers?: GraphQLResolverMap<any>; //note the `any` here
}

因此,使用这样定义的解析器:

export const resolvers: GraphQLResolverMap<Context> = {
  Query: {
    shop(_, _args, ctx) {
      console.log(ctx.datasources.shopify); // Shopify
    },
  },
};

我们现在可以传入(GraphQLSchemaModule | DocumentNode)[]数组:

const server = new ApolloServer({ 
    schema: buildSubgraphSchema([ //note the array
      {
        typeDefs, //DocumentNode
        resolvers, //GraphQLSchemaModule, in this case GraphQLResolverMap<Context>
      },
    ]),
  });

这对我有用,没有 ts 错误,服务器启动得很好。 对社区的建议持开放态度,以获得更好的模式。

最终,我认为 codegen 工具旨在解决很多这些问题。 我现在正在研究这个: https://the-guild.dev/graphql/codegen

玩得开心!

ApolloServer class 是通用的,您应该将自定义上下文指定为类型参数。 请参阅 文档这些单元测试

interface Context {
  dataSources: {
    shopify: Shopify;
  }
}

const server = new ApolloServer<Context>({
//                             ^^^^^^^^^
  schema: buildSubgraphSchema({ 
    typeDefs,
    resolvers: {
      Query: {
        shop(_, _args, ctx: Context) {
          console.log("ctx:", ctx)
        },
      }
    }
  }),
  dataSources: () => ({
    shopify: new Shopify()
  })
});

ApolloServer class 是通用的,您应该将自定义上下文指定为 > 类型参数。 请参阅文档和这些单元测试。

我也这么认为,但它仍然将其视为LegacySchemaModule和 ts croaks ... 我上面更长的答案中的模式现在似乎是这样做的方式?

我尝试了您的代码,但与unknownContext发生了相同类型的冲突:

error TS2345: Argument of type '{ typeDefs: DocumentNode; resolvers: { Query: { shop(_: any, _args: any, ctx: Context): void; }; }; }' is not assignable to parameter of type 'DocumentNode | (DocumentNode | GraphQLSchemaModule)[] | 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'.  
                    ^^^^^^^^^ -- seems to originate in LegacySchemaModule because
                                 we are pssing in {typeDefs,resolvers} as an object
                                 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM