如何从后端 GraphQL 服务器返回 Decimal 类型,然后在前端客户端上解析它?
我有一个返回带有价格的产品的后端。价格是十进制类型的自定义标量。
架构如下:
scalar Decimal
type Product {
id: ID!
price: Decimal
}
我的后端有一个用于十进制类型的自定义解析器,如下所示:
const decimalScalar = new GraphQLScalarType({
name: "Decimal",
description: "Decimal custom scalar type",
serialize(value: number) {
return new Decimal(value);
},
parseValue(value: number) {
return new Decimal(value);
},
parseLiteral(ast) {
if (ast.kind === Kind.FLOAT) {
return new Decimal(parseFloat(ast.value));
}
return null;
}
});
我的后端返回 JSON,如下所示:
[
{
id: "product_1",
price: "12.22" // should this be returning a `__typename: Decimal` some how?
},
{
id: "product_2",
price: "18.05"
}
]
问题是我的前端应用程序收到此数据并认为价格是一个字符串。我想将价格解析回十进制类型。
我在我的 apollo 客户端中包含了一个十进制标量,以便尝试解析该值:
// DecimalScalar.ts
import { GraphQLScalarType, Kind } from 'graphql';
import Decimal from 'decimal.js';
const decimalScalar = new GraphQLScalarType({
name: 'Decimal',
description: 'Decimal custom scalar type',
serialize(value: number) {
return new Decimal(value);
},
parseValue(value: number) {
return new Decimal(value);
},
parseLiteral(ast) {
if (ast.kind === Kind.FLOAT) {
return new Decimal(parseFloat(ast.value));
}
return null;
}
});
export default decimalScalar;
// Apollo Client
const retryLink = new RetryLink();
const httpLink = new HttpLink({ uri: config.API_URL })
const apolloLink = new ApolloLink((operation, forward) => {
operation.setContext({
customScalars: {
Decimal: {
serialize: (value: number) => value.toString(),
parseValue: (value: number) => new Decimal(value),
parseLiteral: decimalScalar.parseLiteral,
},
},
});
return forward(operation);
})
const client = new ApolloClient({
cache: new InMemoryCache(),
link: ApolloLink.from([
retryLink,
httpLink,
apolloLink
])
});
这似乎根本没有解析该值:
console.log(typeof data?.getProducts?.[0].price) // string (price is of type any according to TypeScript)
由于我的
price
值没有 __typename
,Apollo 应该如何知道将价格解析为 DecimalScalar?
价格返回的 JSON 值只是一个字符串,还是应该包含一些
__typename: "Decimal"
或其他内容,这是否正确?
我的 Apollo 客户端中是否正确实现了 DecimalScalar 解析器?
任何帮助将不胜感激,谢谢。
graphql-scalars 包提供了大量开箱即用的自定义标量。它也是开源的,因此是一个很好的学习资源。
查看其 currency 类型的 implementation,它与您的 decimal 类型有些相似。
__typename
,因为它是自定义标量,并且自定义标量没有类型名称为了将正确的类型添加到客户端应用程序中,Apollo 发布了这个教程,介绍如何从架构(包括自定义标量)生成类型,以便客户端使用它们。