Custom scalars on the client side

I have this custom scalar on the server side

new GraphQLScalarType({
  name: 'Date',
  description: 'Date custom scalar type',
  serialize(value) {
    if (value instanceof Date) {
      return value.getTime(); // Convert outgoing Date to timestamp for JSON
    }
    throw Error('GraphQL Date Scalar serializer expected a `Date` object');
  },
  parseValue(value) {
    if (typeof value === 'number') {
      return new Date(value); // Convert incoming timestamp to Date
    }
    throw new Error('GraphQL Date Scalar parser expected a `number`');
  },
  parseLiteral(ast) {
    if (ast.kind === Kind.INT) {
      // Convert hard-coded AST string to timestamp and then to Date
      return new Date(parseInt(ast.value, 10));
    }
    // Invalid hard-coded value (not an integer)
    return null;
  },
});

I wanna do the same thing on the client side, turning Date graphql typed data to javascript Date object when receiving, calling .getTime() and turning into timestamp when sending.

I tried settings typeDefs and resolvers on the Apollo Client. But it doesn’t have any effect.

const client = new ApolloClient({
  uri: 'http://localhost:4000',
  cache: new InMemoryCache(),
  typeDefs: `
    scalar Date
  `,
  resolvers: {
    Date: dateScalar, // same custom scalar as the server side
  }
});
``

Other people seem to wanna do a similar thing Is it possible to map scalars (Date) client-side?

Hey @Dulguun_Otgon :wave:

Unfortunately this isn’t possible right now and is currently in our backlog. It’s a highly requested feature that we want to get to sometime in the next couple minors. Stay tuned to that issue for updates!

You might have some success creating a custom read function in a type policy that parses the field into a date, but I’ve seen some buggy behavior with this from time-to-time (something we plan to look at and fix). Try this and see if this works for you.

new InMemoryCache({
  typePolicies: {
    TypeWithDateScalar: {
      fields: {
        dateField: {
          read: (dateString) => parseDate(dateString)
        }
      }
    }
  }
})

The downside here is that you would need to define a type policy and copy this read function to every field that needs date parsing.

Again, we plan to address this sometime soon which will make this API much more robust and work more as you’d expect. For now I’d suggest either parsing the date in the component where you use this, or trying out the type policy suggestion above.

1 Like

I’m so glad to hear that! Looking forward to it.