Skip to main content

Scalars

GraphQL custom sclars can be defined by placing a @gqlScalar docblock directly before a:

  • Type alias declaration
/**
* A description of my custom scalar.
* @gqlScalar <optional name of the scalar, if different from type name>
*/
export type MyCustomString = string;
note

Grats requires that you export your scalar types so that it may import them into your schema module to define types for the scalars's serialization/deserialization functions.

Built-In Scalars

note

For built-in GraphQL scalars that don't have a corresponding TypeScript type, Grats ships with type aliases you can import. You may be promted to use one of these by Grat if you try to use number in a positon from which Grat needs to infer a GraphQL type.

import { Float, Int, ID } from "grats";

/** @gqlType */
class Math {
id: ID;
/** @gqlField */
round(args: { float: Float }): Int {
return Math.round(args.float);
}
}

Serialization and Parsing of Custom Scalars

When you define a custom scalar, you aslo need to inform the GraphQL executor how to serialize the data (convert the value into something JSON serializable) and how to parse the data (convert a value provided as a variable into the value expected by field arguments). The tree functions you must define are:

  • serialize Converts the return value of a resolver into a JSON serializable value.
  • parseValue Converts the value of a variable into the value expected by a field argument.
  • parseLiteral Converts the value of a literal (included in the query text) into the value expected by a field argument.

Grats ensures you provide serializaiton/deseiralization functions for each of your custom scalars by requiring that you pass them when you call getSchema.

Custom Scalars Example:

For example if you define a Date custom scalar type in your code:

scalars.ts
/** @gqlScalar Date */
export type GqlDate = Date;

The getSchema function that Grats generates will require that you pass a config object with a scalars property, which is an object with a Date property, which is an object specifying serialize/parseValue/parseLiteral transformation functions:

server.ts
import { getSchema } from "./schema"; // Generated by Grats
import { GqlDate } from "./scalars";

const schema = getSchema({
scalars: {
Date: {
serialize: (value: GqlDate): number => value.getTime(),
parseValue(value: unknown): GqlDate {
if (typeof value !== "number") throw new Error("Date is not a number");
return new Date(value);
},
parseLiteral(ast: ValueNode): GqlDate {
if (ast.kind !== "IntValue") throw new Error("Date is not IntValue");
return new Date(Number(ast.value));
},
},
},
});
// ... Continue on, using the schema to create a GraphQL server