Open imaksp opened 4 years ago
Names in GraphQL are limited to this ASCII subset of possible characters to support interoperation with as many other systems as possible.
– https://spec.graphql.org/June2018/#sec-Names
A really nice property of GraphQL names is that they're also valid variable names for virtually all major programming languages. I'd hate to see that go.
IMHO the character set constraint is unnecessarily onerous. Many JSON APIs out there already use all kinds of special characters - it's really common to see field names starting with $ or / which mark a field as having some special significance - for example the IPLD DAG for JSON uses '/' as a field name for links. Far from supporting interoperation, limiting the set of characters makes it harder to add graphQL any existing API. If interoperability is a design requirement for a new API, there is nothing that forces the developer to use these special characters. Recommend instead following the JSON rules for property names, and where issues exist in a given target language simply following whatever workarounds have already been developed for mapping in JSON.
I'd also like to see additional characters allowed specifically in enum members, e.g. +
(as well as -
and /
). (I'm less concerned with type names, but maybe someone else has a need for that.)
As an example, I need to represent letter grades (e.g. A+
, A
, A-
, etc.), which seems like a natural fit for an enum, since letter grades are usually a fixed set of unique elements. What I'd like is to be able to write the obvious enum, i.e.
enum LetterGrade {
A+
A
A-
B+
B
B-
C+
etc...
}
I can't, however, because GraphQL doesn't allow +
or -
in enum members. Instead, I'd have to do something like this:
enum LetterGrade {
A_PLUS
A
A_MINUS
B_PLUS
etc...
}
This is mildly annoying because now I need a client-side transform to change the enum value into the more common letter grade format (A+
, A-
, etc.).
Libraries like graphql-tools
do let you specify resolvers for your enum values (see https://www.graphql-tools.com/docs/scalars#internal-values), but crucially the docs note that "These don't change the public API at all" (emphasis mine). This solves the internal side, because the letter grades will ultimately be stored in their common format, but it still leaves the public-facing side of the API with enum members that have to be manipulated for display to the user, even though they don't differ from how they will be stored.
This is mildly annoying because now I need a client-side transform to change the enum value into the more common letter grade format (A+, A-, etc.).
There is a generic principle that should be followed: internal 'code' names and user visible labels are completely different set of tokens, and live in separate universes, and should never be mixed up. I think most devs out there will agree.
There is a temptation sometimes to directly use the enum value (or some other internal code name) as a user-visible label/token in UI - why not, they are the same. But it is dangerous path; for one thing it never works with localization (when app supports multiple UI languages); the other example is when you need to add a two-word enum value to already existing enum.
Your case with grades, although seems reasonable, is a rare corner case. I do not think it's worth changing GraphQL syntax for this rare case. By the way, what if there are countries/colleges that use some other extra chars in grades? like A* ? should we then change syntax again?
There is a generic principle that should be followed: internal 'code' names and user visible labels are completely different set of tokens, and live in separate universes, and should never be mixed up. I think most devs out there will agree.
Yes, I am completely aware of this, and I practice this elsewhere in my schema and my back-end code. I was going to mention something about that in my original comment but left it out because it didn't seem necessary. I was giving an example of a natural, and fairly common in real life, set of enumerated values, and how a slightly less restrictive character set for enum members would be helpful.
To be clear, I can accomplish what I need to do with GraphQL as it exists right now, just in a way that is more verbose.
I think we should not do this, but regarding letter grades:
This is mildly annoying because now I need a client-side transform to change the enum value into the more common letter grade format (A+, A-, etc.).
You could do this:
type LetterGrade {
normalized: NormalizedLetterGrade
textRepresentation: String
}
enum NormalizedLetterGrade {
A_PLUS
A
A_MINUS
B_PLUS
etc...
}
You can even add something like a hexColor: String
to give even more control to your backend.
When adding something like themes this can then be transformed to hexColor(theme: MyTheme = LIGHT): String
- it will still be backwards-compatible
GraphQL is really expressive this way, just carefully consider what you want on the frontend, and what you want on the backend.
Currently name regex only allows limited characters, it would be good if it can add support for
-
&/
characters.