Skip to main content

Scalars

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

  • Type alias declaration
/**
* A description of my custom scalar.
* @gqlScalar
*/
export type MyCustomString = string;
Playground
"""A description of my custom scalar."""
scalar MyCustomString

The type alias must be exported, since Grats' generated schema module imports it to type your scalar's serialization and parsing 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 prompted to use one of these by Grats if you try to use number in a position from which Grats needs to infer a GraphQL type.

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

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

@specifiedBy Directive​

The GraphQL specification defines the @specifiedBy directive which can be added to custom scalar definitions. The directive provides a "scalar specification URL for specifying the behavior of custom scalar types". Grats' support for annotating your schema with directives lets you add this directive to your custom scalars:

/**
* @gqlScalar
* @gqlAnnotate specifiedBy(url: "https://tools.ietf.org/html/rfc4122")
*/
export type UUID = string;
Playground
scalar UUID @specifiedBy(url: "https://tools.ietf.org/html/rfc4122")

Serialization and Parsing of Custom Scalars​

When defining a custom scalar, Grats will require that when constructing your schema you provide a configuration object for the scalar which can optionally define how to serialize and parse values of that type.

For example if you had a Date type in your schema:

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

Grats' generated getSchema would require a config object where you could supply serialize/parseValue/parseLiteral transforms for this type. If Date were serialized as a Unix timestamp, you could do the following:

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

const config: SchemaConfig = {
scalars: {
Date: {
serialize(value): number {
if (!(value instanceof Date)) {
throw new Error("Date.serialize: value is not a Date object");
}
return value.getTime();
},
parseValue(value): Date {
if (typeof value !== "number") {
throw new Error("Date.parseValue: value is not a number");
}
return new Date(value);
},
parseLiteral(ast): Date {
if (!(ast.kind === "IntValue" || ast.kind === "StringValue")) {
throw new Error(
"Date.parseLiteral: ast.kind is not IntValue or StringValue",
);
}
return new Date(Number(ast.value));
},
},
},
};

const schema = getSchema(config);

// ... Continue on, using the schema to create a GraphQL server