簡體   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