Typesafe serialization and deserialization of scalars
See original GitHub issueIs your feature request related to a problem? Please describe.
We use a lot of custom scalars in our schema. Following are three small examples:
"""The `Date` scalar represents an ISO-8601 compliant date type."""
scalar Date
"""The `DateTime` scalar represents an ISO-8601 compliant date time type."""
scalar DateTime
"""The WeekYear scalar represent an ISO Week compliant week year type. yyyy-Www"""
scalar WeekYear
Currently, the only option we have been able to find is to use the ScalarsMap
to map them to strings respectively:
scalars:
Date: string
DateTime: string
WeekYear: string
I am aware of the fact that you can map scalars to custom types aside from string too, but serializing to Date obviously doesnt work since graphql-codegen has no concept(that im aware of) that allows specifying how a specific scalar is deserialized. That leaves me with what we have currently, which is telling graphql-codegen that the scalar should be mapped to string and then deserialize them at every occurence in my code which results in noisy and repetitive code for both mutations and queries.
Describe the solution you’d like I would like to have some way to specify scalar types on the client safely. Here is my general idea:
- Add a new config value
scalarMappers
- The scalarMappers value points to a folder containing all the scalarMappers
- ScalarMappers need to adhere to this interface:
interface ScalarMapper<T> {
resultingTypeName(): string
deserializeValue(value: any): T
serializeValue(value: T): string
}
- Users could then declare typesafe parsers for scalar values:
import { parseISO } from "date-fns";
class DateTimeMapper implements ScalarMapper<Date> {
resultingTypeName(): string {
return 'Date';
}
deserializeValue(value: any): Date {
if(typeof value !== 'string') {
throw new Error('Could not deserialize value');
}
return parseISO(value);
}
serializeValue(value: Date): string {
return value.toISOString();
}
}
Describe alternatives you’ve considered The current workaround we use is outlined in the first bullet point. Another option i considered was writing a custom plugin, but from the docs it seemed like that would require me to fork the typescript plugin since i want to modify the output of that. If theres a way to modify the output of the typescript plugin, let me know please. I sadly wasnt able to find one.
Issue Analytics
- State:
- Created 2 years ago
- Reactions:11
- Comments:7 (1 by maintainers)
I’m facing the same issue. My only idea is to serialize & deserialize date fields wherever they are read from / written to in the code which leads to a lot of boilerplate code.
@ardatan you wrote
What do you mean with ‘as part of the client library’? How could I write a central de-serializer that codegen uses for
Date
orDatetime
scalars? As far as I know, I can only supply types with thescalars:
config. Or is the only way to serialize / deserialize the scalar fields whenever they are accessed?If I understand correctly, the thing @mastorm pointing is serialization/deserialization and type safety. We can declare scalars map like
DateTime: MyDateTime
and it looks working fine in compile time but runtime because there is no serialization process fromstring
toMyDateTime
.To work around, I’m using Branded Type:
and declare
scalars
:then write a serializer from
MyDateTime
toDateTime
you would like to use (i.e. luxon).Serializer issue still remains but type safety could be assured.