TypeGraphQL中使用ethers.js BigNumber类型触发CannotDetermineGraphQLTypeError错误的技术问询
The error pops up because TypeGraphQL doesn't natively recognize ethers.js's BigNumber type. Unlike standard TypeScript types or built-in GraphQL scalars, custom types like BigNumber need a dedicated GraphQL scalar definition to work seamlessly with TypeGraphQL. Here are two solid solutions:
Option 1: Create a Custom GraphQL Scalar for BigNumber (Recommended)
This approach lets TypeGraphQL fully understand BigNumber, handling serialization/deserialization automatically between your API and clients.
Step 1: Implement the Custom Scalar
Make a scalar class to handle conversions between BigNumber and GraphQL's string representation (since GraphQL doesn't have a native big number type):
import { Scalar, CustomScalar } from 'type-graphql'; import { ValueNode, Kind } from 'graphql'; import { BigNumber } from 'ethers'; @Scalar('BigNumber') export class BigNumberScalar implements CustomScalar<string, BigNumber> { description = 'Custom scalar type for ethers.js BigNumber values'; // Convert BigNumber to string for GraphQL output serialize(value: BigNumber): string { if (!(value instanceof BigNumber)) { throw new Error('BigNumberScalar can only serialize BigNumber instances'); } return value.toString(); } // Convert incoming string value to BigNumber parseValue(value: string): BigNumber { return BigNumber.from(value); } // Parse GraphQL AST literal to BigNumber parseLiteral(ast: ValueNode): BigNumber { if (ast.kind === Kind.STRING) { return BigNumber.from(ast.value); } throw new Error('BigNumberScalar only supports string literals'); } }
Step 2: Use the Scalar in Your Entity
Update your Transfer entity to reference the custom scalar in the @Field decorator:
@ObjectType() @Entity() export class Transfer extends BaseEntity { @Field(() => BigNumberScalar) // Explicitly specify the custom scalar @Column({ type: "numeric", precision: 78, scale: 0, transformer: new BigNumberTransformer() }) amount!: BigNumber; }
Step 3: Register the Scalar with TypeGraphQL
When building your GraphQL schema, register the scalar so TypeGraphQL recognizes it:
import { buildSchema } from 'type-graphql'; import { BigNumberScalar } from './BigNumberScalar'; import { Transfer } from './Transfer'; async function bootstrap() { const schema = await buildSchema({ resolvers: [/* Your resolvers here */], entities: [Transfer], scalarsMap: [{ type: BigNumber, scalar: BigNumberScalar }], }); // Use the schema with your server (Apollo, etc.) }
Option 2: Explicitly Map BigNumber to GraphQL String Type
If you don't want to create a custom scalar, you can directly tell TypeGraphQL to treat amount as a string. This works because your TypeORM transformer already converts BigNumber to/from strings for the database:
@ObjectType() @Entity() export class Transfer extends BaseEntity { @Field(() => String) // Force GraphQL to output a string @Column({ type: "numeric", precision: 78, scale: 0, transformer: new BigNumberTransformer() }) amount!: BigNumber; }
Note: With this approach, your API clients will receive the value as a string, and they'll need to convert it back to a BigNumber using ethers.BigNumber.from() if needed.
Key Notes
- Your existing
BigNumberTransformerfor TypeORM is still valid and handles database conversion — these solutions only fix the TypeGraphQL type mapping. - If you're using NestJS with
@nestjs/graphql, register the scalar as a provider in your module instead of usingscalarsMap:@Module({ providers: [BigNumberScalar], }) export class YourModule {}
内容的提问来源于stack exchange,提问作者sev

