Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

graphql, union scalar type?

Tags:

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?

like image 210
slideshowp2 Avatar asked Apr 18 '18 10:04

slideshowp2


People also ask

What is a union type in GraphQL?

Unions and interfaces are abstract GraphQL types that enable a schema field to return one of multiple object types.

What are GraphQL scalar 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.

What other types can be used in a GraphQL schema?

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.

What is __ Typename in GraphQL?

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).


1 Answers

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 
like image 168
Daniel Rearden Avatar answered Sep 21 '22 05:09

Daniel Rearden