简体   繁体   English

使用带有 typegraphql 的非标准类型 (BigNumber)

[英]Using a non-standard type (BigNumber) with typegraphql

I have an ethers.js BigNumber that I am storing in Postgresql DB as a numeric type using TypeORM.我有一个ethers.js BigNumber ,我使用 TypeORM 作为numeric类型存储在 Postgresql DB 中。 I am trying to make it work with Typegraphql but I am getting the error: CannotDetermineGraphQLTypeError: Cannot determine GraphQL output type for 'amount' of 'Transfer' class. 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?我正在尝试使其与 Typegraphql 一起使用,但出现错误: CannotDetermineGraphQLTypeError: Cannot determine GraphQL output type for 'amount' of 'Transfer' class. 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? CannotDetermineGraphQLTypeError: Cannot determine GraphQL output type for 'amount' of 'Transfer' class. 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?

@ObjectType()
@Entity()
export class Transfer extends BaseEntity {
  @Field()
  @Column({
    type: "numeric",
    precision: 78,
    scale: 0,
    transformer: new BigNumberTransformer()
  })
  amount!: BigNumber
}

I created a BigNumberTransformer as was recommended in this medium post :我创建了一个BigNumberTransformer ,正如这篇中篇文章中所推荐的那样:

export class BigNumberTransformer implements ValueTransformer {
  to(num: BigNumber): string {
    return num.toString();
  }

  from(num: string): BigNumber {
    return BigNumber.from(num);
  }
}

You must create a custom scalar ( BigNumber.ts ):您必须创建一个自定义标量( BigNumber.ts ):

import { Kind, GraphQLError, GraphQLScalarType } from "graphql";
import { BigNumber } from "ethers";

export const GraphQLBigNumber: GraphQLScalarType = new GraphQLScalarType({
  name: "BigNumber",

  description:
    "A field whose value is a valid BigNumber which safely allows mathematical operations on numbers of any magnitude",

  serialize(value) {
    if (value === null) return value;
    else return BigNumber.from(value.toString()).toString();
  },

  parseValue(value) {
    if (value === null) return value;
    else return BigNumber.from(value.toString());
  },

  parseLiteral(ast) {
    if (ast.kind !== Kind.STRING && ast.kind !== Kind.Int) {
      throw new GraphQLError(
        `Can only validate strings or ints as BigNumbers but got a: ${ast.kind}`
      );
    }

    if (ast.value === null) return ast.value;
    else return BigNumber.from(value.toString());
  },

  extensions: {
    codegenScalarType: "BigNumber | string | number",
  },
});

Then you can just use it in your field decorator:然后你可以在你的字段装饰器中使用它:

// ...
import { GraphQLBigNumber } from "./BigNumber";

@ObjectType()
@Entity()
export class Transfer extends BaseEntity {
  @Field(() => GraphQLBigNumber) // Here!
  @Column({
    type: "numeric",
    precision: 78,
    scale: 0,
    transformer: new BigNumberTransformer(),
  })
  amount!: BigNumber;
}

Optionally, you can declare the association between the reflected property type and your scalar to automatically map it (no need for explicit type annotation:):或者,您可以声明反射属性类型和标量之间的关联以自动 map 它(不需要显式类型注释:):

@ObjectType()
@Entity()
export class Transfer extends BaseEntity {
  @Field() // Magic goes here - no type annotation!
  @Column({
    type: "numeric",
    precision: 78,
    scale: 0,
    transformer: new BigNumberTransformer(),
  })
  amount!: BigNumber;
}

All you need to do is register the association map in the buildSchema options:您需要做的就是在buildSchema选项中注册关联 map:

import { buildSchema } from "type-graphql";
import { BigNumber } from "ethers";
import { GraphQLBigNumber } from "./BigNumber";

const schema = await buildSchema({
  resolvers,
  scalarsMap: [{ type: BigNumber, scalar: GraphQLBigNumber }],
});

However, you must be aware that this will only work when the TypeScript reflection mechanism can handle it.但是,您必须知道,这仅在 TypeScript 反射机制可以处理时才有效。 So our class property type must be a class , not an enum , union or interface .所以我们的 class 属性类型必须是class ,而不是enumunioninterface

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

相关问题 非标准TypeScript接口/类字段 - non-standard TypeScript interface/class fields TypeGraphql 和 Prisma 2 类型冲突 - TypeGraphql and Prisma 2 type conflicts Svelte 中非标准窗口事件的 TypeScript 类型 - TypeScript typing of non-standard window event in Svelte react typescript eslint plugin - 文件的扩展名 (.svg) 是非标准的 - react typescript eslint plugin - The extension for the file (.svg) is non-standard ESLint:防止被 lint 非标准文件扩展名 - ESLint: prevent from being linted non-standard files extensions TypeGraphQL:使用从本地 Package 导入的 GraphQL class 时出现@Arg 类型错误 - TypeGraphQL : @Arg Type Error when using a GraphQL class imported from a local Package 为什么 TypeGraphQL 不能确定泛型的类型? - Why can't TypeGraphQL determine the type of a generic? typegraphql:使用变量时在操场上出现参数错误 - typegraphql : parameter error in playground when using variables 为什么允许使用 kebab-case 非标准属性,而不允许使用其他属性? 以及如何在 TypeScript 中定义这样的类型? - Why kebab-case non-standard attributes are allowed while others aren't? And how to define types like this in TypeScript? 使用 TypeGraphQL 在浏览器中为 Apollo 本地状态生成 typedef 和解析器 - Using TypeGraphQL to generate typedefs and resolvers for Apollo local state in browser
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM