简体   繁体   English

为什么 TypeGraphQL 不能确定泛型的类型?

[英]Why can't TypeGraphQL determine the type of a generic?

I'm trying to define generic type definitions for building connections and edges in GraphQL.我正在尝试为在 GraphQL 中构建连接和边缘定义通用类型定义。 I'm keeping with the Relay spec, except that I'm also including the conventional nodes connection property for convenience.我与 Relay 规范保持一致,除了为方便起见我还包括常规nodes连接属性。 The TypeGraphQL docs show how to do something very similar, but I'm getting the following error when I try to run the server: TypeGraphQL 文档展示了如何做一些非常相似的事情,但是当我尝试运行服务器时出现以下错误:

Cannot determine GraphQL output type for 'nodes' of 'Connection' class.无法确定“连接”class 的“节点”的 GraphQL output 类型。 Is the value, that is used as its TS type or explicit type, decorated with a proper decorator or is it a proper output value?用作其 TS 类型或显式类型的值是用适当的装饰器装饰还是适当的 output 值?

Typically, this shows up when the @ObjectType decorator is missing from a class definition which is then used as a field type somewhere else;通常,当 class 定义中缺少@ObjectType装饰器时,就会出现这种情况,然后将其用作其他地方的字段类型; however, I've confirmed that the types I'm passing have definitely been defined with this decorator, and I've also tried with a few different types from my schema.但是,我已经确认我传递的类型肯定是用这个装饰器定义的,而且我也尝试过使用我的模式中的几种不同类型。 The docs demonstrate using a generic as a field definition, so that doesn't seem to be the issue either.文档演示了使用泛型作为字段定义,因此这似乎也不是问题。

My type definitions are as follows:我的类型定义如下:

interface RawEdge<NodeType> {
  node: NodeType
}

interface Edge<NodeType> extends RawEdge<NodeType> {
  cursor: string
}

function Edge<NodeType>(NodeClass: ClassType<NodeType>) {
  @ObjectType({ isAbstract: true })
  abstract class Edge {
    constructor(identifier: string, node: NodeType) {
      this.cursor = Buffer.from(identifier).toString('base64')
      this.node = node
    }

    @Field()
    cursor: string

    @Field(type => NodeClass)
    node: NodeType
  }

  return Edge
}


interface Connection<NodeType, EdgeType extends Edge<NodeType>> {
  totalCount: number
  edges: EdgeType[]
  nodes: NodeType[]
  pageInfo: PageInfo
}

function Connection<NodeType, EdgeType extends Edge<NodeType>>(
  NodeClass: ClassType<NodeType>,
  EdgeClass: ClassType<Edge<NodeType>>
) {
  @ObjectType({ isAbstract: true })
  abstract class Connection {
    constructor(edges: EdgeType[], page: PageQuery) {
      this.totalCount = edges.length
      this.edges = edgesToReturn<EdgeType>(edges, page)
      this.nodes = this.edges.map(edge => edge.node)
      this.pageInfo = pageInfo(this, edges)
    }

    @Field(type => Int)
    totalCount: number

    @Field(type => [EdgeClass])
    edges: EdgeType[]

    @Field(type => [NodeClass])
    nodes: NodeType[]

    @Field()
    pageInfo: PageInfo
  }

  return Connection
}

EDIT: The following workaround resolves the type issue, which proves that the types being passed in have the proper decorators in their definition.编辑:以下解决方法解决了类型问题,这证明传入的类型在其定义中具有适当的装饰器。 However, this is extremely clunky, so I would like to avoid having to use it if possible.但是,这非常笨重,所以我想尽可能避免使用它。

function Edge<NodeType>(NodeClass: ClassType<NodeType>) {
  @ObjectType({ isAbstract: true })
  abstract class Edge {
    constructor(identifier: string, node: NodeType) {
      this.cursor = Buffer.from(identifier).toString('base64')
      this.node = node
    }

    @Field()
    cursor: string

    // @Field decorator removed
    node: NodeType
  }

  return Edge
}

function Connection<NodeType, EdgeType extends Edge<NodeType>>(
  NodeClass: ClassType<NodeType>,
  EdgeClass: ClassType<Edge<NodeType>>
) {
  @ObjectType({ isAbstract: true })
  abstract class Connection {
    constructor(edges: EdgeType[], page: PageQuery) {
      this.totalCount = edges.length
      this.edges = edgesToReturn<EdgeType>(edges, page)
      this.nodes = this.edges.map(edge => edge.node)
      this.pageInfo = pageInfo(this, edges)
    }

    @Field(type => Int)
    totalCount: number

    @Field(type => [EdgeClass])
    edges: EdgeType[]

    // @Field decorator removed
    nodes: NodeType[]

    @Field()
    pageInfo: PageInfo
  }

  return Connection
}

type RawDepartmentProductEdge = RawEdge<Product>

@ObjectType()
class DepartmentProductEdge extends Edge(Product) {
  // Define the field type here instead of in the generic
  @Field(type => Product)
  node: Product
}

@ObjectType()
class DepartmentProductConnection extends Connection(Product, DepartmentProductEdge) {
  // Define the field type here instead of in the generic
  @Field(type => [Product])
  nodes: Product[]
}

Context, for anyone who's curious:上下文,对于任何好奇的人:

The purpose of all this is to generate connections using something like this...所有这些的目的是使用这样的东西生成连接......

type RawDepartmentProductEdge = RawEdge<Product>

@ObjectType()
class DepartmentProductEdge extends Edge(Product) {}

@ObjectType()
class DepartmentProductConnection extends Connection(Product, DepartmentProductEdge) {}

...and then populate them like this... ...然后像这样填充它们...

const products = [] // Retrieve the products here
const edges = products.map(node => new DepartmentProductEdge(node.id, node)
const connection = new DepartmentProductConnection(edges, pagination)

...so that everything is as DRY as possible, but I can still add meta to the edges as needed. ...所以一切都尽可能干燥,但我仍然可以根据需要将元添加到边缘。

As it turns out, the code above works just fine: the problem was in sequencing my imports.事实证明,上面的代码工作得很好:问题在于我的导入排序。 I'm using a "bucket" file for exporting all of my GraphQL types, and while that works fine for bringing them into resolvers or middleware, importing from the bucket within type definitions causes weird circular dependency issues.我正在使用“桶”文件来导出我的所有 GraphQL 类型,虽然这可以很好地将它们带入解析器或中间件,但从类型定义中的桶导入会导致奇怪的循环依赖问题。

The solution is just to import types directly from their source files when doing type declarations.解决方案是在进行类型声明时直接从源文件中导入类型。 So, specifically as it applies to the example above:因此,特别适用于上面的示例:

// File system

schema
|- connection
| |- Connection.ts
| |- DepartmentProductConnection.ts
| |- Edge.ts
| |- PageInfo.ts
|- department
| |- Department.ts
|- product
| |- Product.ts
|- index.ts
// index.ts

export * from './connection/Connection'
export * from './connection/Edge'
export * from './connection/PageInfo'
export * from './connection/DepartmentProductConnection'

export * from './department/Department'
export * from './product/Product'
// DepartmentProductConnection.ts

import { ObjectType } from 'type-graphql'

// Don't do this!
// import { Connection, Edge, Product, RawEdge } from '..'

// Instead, do this.
import { Product } from '../product/Product'
import { Connection } from './Connection'
import { Edge, RawEdge } from './Edge'

type RawDepartmentProductEdge = RawEdge<Product>

@ObjectType()
class DepartmentProductEdge extends Edge(Product) {}

@ObjectType()
class DepartmentProductConnection extends Connection(Product, DepartmentProductEdge) {}

暂无
暂无

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

相关问题 为什么不能推断出这些泛型类型? - Why can't these generic type be inferred? 为什么我不能将打字稿泛型类型分配给该类型的联合? - Why can't I assign a typescript generic type to a union of that type? 为什么 Typescript 不能推断嵌套泛型函数的类型? - Why can't Typescript infer the type of a nested generic function? 为什么我不能使用联合类型参数调用泛型函数? - Why can't I call a generic function with a union type parameter? 为什么TypeScript在嵌套对象中不能推断泛型类型? - Why can't TypeScript infer a generic type when it is in a nested object? 为什么 typescript 不能通过其字段推断泛型类型? - Why typescript can't infer the generic type by its fields? TypeGraphql 和 Prisma 2 类型冲突 - TypeGraphql and Prisma 2 type conflicts 错误:在 typegraphql 中将数组作为输入类型传递时,无法确定 GraphQL 输入类型 - Error: Cannot determine GraphQL input type when passing array as input type in typegraphql 为什么我不能使这种类型通用? 类型“x”不能用于索引类型“y”ts(2536) - Why can't I make this type generic? Type "x" cannot be used to index type "y" ts(2536) 为什么泛型类型参数 T 在返回类型中是“未知的”? 如何键入此 function 以便正确推断返回类型? - Why is the generic type parameter T “unknown” in the return type? How can I type this function so that the return type is correctly inferred?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM