Reputation: 3417
I'm trying to create what I thought would be a Union or Enum for Apollo GraphQL, however, my understanding is at noob level. What is the correct way to write the code below.
Path: sampleType.graphql
union GridSize = 'auto' | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
type Element {
xs: GridSize
}
Upvotes: 0
Views: 716
Reputation: 3597
GraphQL doesn't support string literals or numerical literals like you're doing. In TypeScript, for example, you can use literals like that:
type GridSize = 'auto' | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
GraphQL doesn't have anything like that. You can use enums:
enum GRID_SIZE {
SOME_VALUE_HERE
SECOND_OPTION
}
but unfortunately, your example won't work because the values in enums have to follow this regular expression /[_A-Za-z][_0-9A-Za-z]*/
, which means it can't start with (or be only) a number.
So what can you do?
You can use Dani R's commented answer, and just create a union that accepts an Int | String
. This is the easiest thing. Alternatively, if you want to make this its own type "for real" – which acts the way you're describing it (mostly) – you can create a custom scalar:
"""
The following values are accepted
'auto' | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
"""
scalar GridSize
type Element {
xs: GridSize
}
Then you need to create your scalar resolvers:
const { GraphQLScalarType, Kind } = require('graphql')
const allowedValues = ['auto', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
const gridSizeScalar = new GraphQLScalarType({
name: 'GridSize',
description: `
The following values are accepted
'auto' | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
`,
serialize(value) {
// outgoing from your code
if (!allowedValues.includes(value)) {
// or you could throw, but your own code had better not return bad values :)
console.error('something')
return null
}
return value
},
parseValue(value) {
// incoming from input
if (!allowedValues.includes(value)) {
// you probably have a better error message than I do
throw new RangeError('Not a valid Grid Size')
}
return value
},
parseLiteral(ast) {
if ((ast.kind !== Kind.INT) && (ast.kind !== Kind.STRING)) {
// if this value isn't a string or number, it's definitely not OK
return null
}
return ast.value
}
})
and just stick that in your resolvers
const resolvers = {
Query: {},
Mutation: {},
Whatever: {},
GridSize: gridSizeScalar
}
Upvotes: 1