The payload
field can be Int
or String
scalar type. when I write it like union type:
const schema = ` input QuickReply { content_type: String title: String payload: Int | String image_url: String } `
I got an error:
GraphQLError: Syntax Error GraphQL request (45:18) Expected Name, found | 44: title: String 45: payload: Int | String ^ 46: image_url: String
It seems GraphQL
does not support the union scalar type.
So, how can I solve this situation?
Unions and interfaces are abstract GraphQL types that enable a schema field to return one of multiple object types.
The GraphQL specification includes default scalar types Int , Float , String , Boolean , and ID . Although these scalars cover the majority of use cases, some applications need to support other atomic data types (such as Date ) or add validation to an existing type. To enable this, you can define custom scalar types.
The GraphQL schema language supports the scalar types of String , Int , Float , Boolean , and ID , so you can use these directly in the schema you pass to buildSchema . By default, every type is nullable - it's legitimate to return null as any of the scalar types.
The __typename field returns the object type's name as a String (e.g., Book or Author ). GraphQL clients use an object's __typename for many purposes, such as to determine which type was returned by a field that can return multiple types (i.e., a union or interface).
Scalars can't be used as part of unions, since per the specification, unions specifically "represent an object that could be one of a list of GraphQL Object types." Instead, you can use a custom scalar. For example:
const MAX_INT = 2147483647 const MIN_INT = -2147483648 const coerceIntString = (value) => { if (Array.isArray(value)) { throw new TypeError(`IntString cannot represent an array value: [${String(value)}]`) } if (Number.isInteger(value)) { if (value < MIN_INT || value > MAX_INT) { throw new TypeError(`Value is integer but outside of valid range for 32-bit signed integer: ${String(value)}`) } return value } return String(value) } const IntString = new GraphQLScalarType({ name: 'IntString', serialize: coerceIntString, parseValue: coerceIntString, parseLiteral(ast) { if (ast.kind === Kind.INT) { return coerceIntString(parseInt(ast.value, 10)) } if (ast.kind === Kind.STRING) { return ast.value } return undefined } })
This code effectively combines the behaviors for both the Int and String types, while still enforcing the range for 32-bit signed integers. However, you could have whatever type coercion behavior you want. Check out the source code to see how the built-in scalars work, or this article for more details around how custom scalars work.
Note that if you're trying to return one of several scalars for an output field, it's possible to utilize a union for the parent type to achieve a similar result. For example, this isn't possible:
type Post { content: String | Int }
but you can do the following:
type PostString { content: String } type PostInt { content: Int } union Post = PostString | PostInt
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With