Scalars
A GraphQL object type has a name and fields, but at some point those fields have to resolve to some concrete data. Scalar types provide that data: they represent the leaves of the query (see scalar types in the GraphQL documentation). GraphQL includes the following built-in scalar types: Int, Float, String, Boolean, and ID. In addition to these, you may need to support custom atomic data types (e.g., Date).
Code first#
The code first approach ships with five scalars, three of which are aliases for the existing GraphQL types:
ID(alias forGraphQLID): a unique identifier, often used to refetch an object or as the key for a cacheInt(alias forGraphQLInt): a signed 32-bit integerFloat(alias forGraphQLFloat): a signed double-precision floating-point valueGraphQLISODateTime: a date-time string in UTC (used by default to represent theDatetype)GraphQLTimestamp: a signed integer that represents a date and time as the number of milliseconds since the start of the Unix epoch
By default, GraphQLISODateTime (e.g., 2019-12-03T09:54:33Z) represents the Date type. To use GraphQLTimestamp instead, set the dateScalarMode property of the buildSchemaOptions object to 'timestamp':
GraphQLModule.forRoot({
buildSchemaOptions: {
dateScalarMode: 'timestamp',
}
}),
Likewise, GraphQLFloat represents the number type by default. To use GraphQLInt instead, set the numberScalarMode property of the buildSchemaOptions object to 'integer':
GraphQLModule.forRoot({
buildSchemaOptions: {
numberScalarMode: 'integer',
}
}),
You can also create custom scalars.
Override a default scalar#
To create a custom implementation of the Date scalar, create a new class:
import { Scalar, CustomScalar } from '@nestjs/graphql';
import { Kind, ValueNode } from 'graphql';
@Scalar('Date', () => Date)
export class DateScalar implements CustomScalar<number, Date> {
description = 'Date custom scalar type';
parseValue(value: unknown): Date {
return new Date(value as number); // value from the client
}
serialize(value: unknown): number {
return (value as Date).getTime(); // value sent to the client
}
parseLiteral(ast: ValueNode): Date | null {
if (ast.kind === Kind.INT) {
return new Date(parseInt(ast.value, 10));
}
return null;
}
}
With this in place, register DateScalar as a provider:
@Module({
providers: [DateScalar],
})
export class CommonModule {}
Now you can use the Date type in your classes:
@Field()
creationDate: Date;
Import a custom scalar#
To use a custom scalar, import it and register it as a resolver. For demonstration purposes, we'll use the graphql-type-json package, which defines a JSON GraphQL scalar type.
Start by installing the package:
$ npm i --save graphql-type-json
Once the package is installed, pass a custom resolver to the forRoot() method:
import GraphQLJSON from 'graphql-type-json';
@Module({
imports: [
GraphQLModule.forRoot({
resolvers: { JSON: GraphQLJSON },
}),
],
})
export class AppModule {}
Now you can use the JSON type in your classes:
@Field(() => GraphQLJSON)
info: JSON;
For a suite of ready-made scalars, see the graphql-scalars package.
Create a custom scalar#
To define a custom scalar, create a new GraphQLScalarType instance. The following example creates a custom UUID scalar:
import { GraphQLScalarType, Kind } from 'graphql';
const regex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
function validate(uuid: unknown): string | never {
if (typeof uuid !== 'string' || !regex.test(uuid)) {
throw new Error('invalid uuid');
}
return uuid;
}
export const CustomUuidScalar = new GraphQLScalarType({
name: 'UUID',
description: 'A simple UUID parser',
serialize: (value) => validate(value),
parseValue: (value) => validate(value),
parseLiteral: (ast) =>
validate(ast.kind === Kind.STRING ? ast.value : undefined),
});
Then pass a custom resolver to the forRoot() method:
@Module({
imports: [
GraphQLModule.forRoot({
resolvers: { UUID: CustomUuidScalar },
}),
],
})
export class AppModule {}
Now you can use the UUID type in your classes:
@Field(() => CustomUuidScalar)
uuid: string;
Schema first#
To define a custom scalar (see custom scalars in the GraphQL Tools documentation), create a type definition and a dedicated resolver. As in the official documentation, we'll use the graphql-type-json package, which defines a JSON GraphQL scalar type.
Start by installing the package:
$ npm i --save graphql-type-json
Once the package is installed, pass a custom resolver to the forRoot() method:
import GraphQLJSON from 'graphql-type-json';
@Module({
imports: [
GraphQLModule.forRoot({
typePaths: ['./**/*.graphql'],
resolvers: { JSON: GraphQLJSON },
}),
],
})
export class AppModule {}
Now we can use the JSON scalar in our type definitions:
scalar JSON
type Foo {
field: JSON
}
Another way to define a scalar type is to create a class. Suppose you want to add a Date type to your schema:
import { Scalar, CustomScalar } from '@nestjs/graphql';
import { Kind, ValueNode } from 'graphql';
@Scalar('Date')
export class DateScalar implements CustomScalar<number, Date> {
description = 'Date custom scalar type';
parseValue(value: unknown): Date {
return new Date(value as number); // value from the client
}
serialize(value: unknown): number {
return (value as Date).getTime(); // value sent to the client
}
parseLiteral(ast: ValueNode): Date | null {
if (ast.kind === Kind.INT) {
return new Date(parseInt(ast.value, 10));
}
return null;
}
}
With this in place, register DateScalar as a provider:
@Module({
providers: [DateScalar],
})
export class CommonModule {}
Now you can use the Date scalar in your type definitions:
scalar Date
By default, the generated TypeScript definition for every custom scalar is any, which isn't type-safe. You can configure how Nest generates typings for your custom scalars when you specify how to generate types:
import { GraphQLDefinitionsFactory } from '@nestjs/graphql';
import { join } from 'node:path';
const definitionsFactory = new GraphQLDefinitionsFactory();
definitionsFactory.generate({
typePaths: ['./src/**/*.graphql'],
path: join(process.cwd(), 'src/graphql.ts'),
outputAs: 'class',
defaultScalarType: 'unknown',
customScalarTypeMapping: {
DateTime: 'Date',
BigNumber: '_BigNumber',
},
additionalHeader: "import _BigNumber from 'bignumber.js'",
});
Hint Alternatively, you can use a type reference, for example,DateTime: Date. In this case,GraphQLDefinitionsFactoryuses thenameproperty of the specified type (Date.name) to generate the TypeScript definitions. For custom (non-built-in) types, you must also add an import statement.
Now, given the following GraphQL custom scalar types:
scalar DateTime
scalar BigNumber
scalar Payload
Nest generates the following TypeScript definitions in src/graphql.ts:
import _BigNumber from 'bignumber.js';
export type DateTime = Date;
export type BigNumber = _BigNumber;
export type Payload = unknown;
Here, the customScalarTypeMapping property maps each custom scalar to the TypeScript type to declare for it. The additionalHeader property adds any imports these type definitions require. Lastly, setting defaultScalarType to 'unknown' aliases any custom scalar not listed in customScalarTypeMapping to unknown instead of any, which TypeScript recommends since version 3.0 for added type safety.
Hint The example imports_BigNumberfrombignumber.jsunder an alias to avoid circular type references.

