如何在 Apollo Server 中正确键入上下文对象?

Posted

技术标签:

【中文标题】如何在 Apollo Server 中正确键入上下文对象?【英文标题】:How can I correctly type the context object in Apollo Server? 【发布时间】:2020-11-19 08:51:39 【问题描述】:

我正在将apollo server 与打字稿一起使用,我无法在解析器中获取上下文参数以获取context 上的name 属性是一个字符串。现在它被输入为any,我希望它被输入为string。我还看到context 参数的类型是any,而我希望它是一个特定的接口。无论如何要告诉上下文和它的属性我想要它是什么类型而不是它们都被输入为any

const server = new ApolloServer(
  typeDefs: gql`
    type Query 
      test: String
    
  `,
  resolvers: 
    Query: 
      test(parent: any, args: any, context, info: any) 
        context.name // name is typed as "any" when I'd like it to be typed as "string"
      
    
  ,
  context() 
    return  
      name: 'John Doe' 
    
  
)

我试图做这样的事情,但这会引发错误。

context< name: string >() 
  return  
    name: 'John Doe' 
  

我确实通过明确地告诉上下文它需要什么来让它工作,但这种方式似乎有点乏味,因为我必须将 Context 导入每个解析器文件并手动转换。

interface Context 
  name: string


const server = new ApolloServer(
  ...
  resolvers: 
    Query: 
      test(parent: any, args: any, context: Context, info: any) 
        context.name // name is typed as "string" here because I used "context: Context" explicitly
      
    
  
  ...
)

【问题讨论】:

【参考方案1】:

如果你是 graphql-code-generator 来生成你的类型,你可以在 codegen.yml 中配置上下文类型:

generates:
  src/generated/graphql.ts:
    config:
      contextType: "src/types#Context"

然后定义你的上下文类型:

export interface Context 
  username: string;

现在解析器方法的context 参数将输入Context,而无需导入类型或进行任何其他更改。

【讨论】:

【参考方案2】:

默认情况下,您提供给 ApolloServerConfig 对象上的 resolvers 字段对任何类型都是开放的,但您可以使用 TypeScript 进行自己的类型缩小。

作为参考,ApolloServer 接受 IResolvers 对象的实例或数组,如下所述:https://github.com/apollographql/apollo-server/blob/a241d34e9275bf6a23cf7aa3ddee57f90de7b364/packages/apollo-server-core/src/types.ts#L90。 IResolvers 具有泛型类型参数,但默认为任何类型参数:https://github.com/ardatan/graphql-tools/blob/8c8d4fc09ddc63c306db16d7386865ac297794bd/packages/utils/src/Interfaces.ts#L298。在您的代码示例中,Query 是构成 IResolverstest() 实现 IFieldResolver: https://github.com/ardatan/graphql-tools/blob/8c8d4fc09ddc63c306db16d7386865ac297794bd/packages/utils/src/Interfaces.ts#L236 的特定类型之一。

您可以利用IResolvers 具有泛型参数这一事实来限制context 参数的类型。例如,通过在赋值左侧显式指定类型,您可以告诉编译器在右侧期望什么:

interface Context 
  username: string


const myResolvers: IResolvers<any, Context> = 
  Query: 
    test: (parent, args, context) => 
      console.log(context.username) // based on generics TS knows context is supposed to be of type Context
    
  


new ApolloServer(
  ...
  resolvers: myResolvers,
  ...

【讨论】:

以上是关于如何在 Apollo Server 中正确键入上下文对象?的主要内容,如果未能解决你的问题,请参考以下文章

req 在 Apollo Server 上下文中始终未定义

在 Apollo Server 上下文中获取 NextAuth.js 用户会话

如何正确互连 Apollo Server/mongodb/express?

从上下文中获取模型与导入 - apollo server express & mongoose

升级到 apollo-server-express 2.0.0 缺少上下文

Apollo Server:dataSources vs context 与数据库一起使用