Working with Scalar Types
1. Using Built-in Scalars
| Scalar | JSON Type | Description |
| Int | number | Signed 32-bit integer |
| Float | number | Signed double-precision floating point |
| String | string | UTF-8 character sequence |
| Boolean | boolean | true or false |
| ID | string | Unique identifier; serialized as String, accepts Int input |
2. Defining Custom Scalar Types
| Method | Direction | Purpose |
| serialize(value) | Server → Client | Convert internal value to JSON |
| parseValue(value) | Client → Server (variables) | Validate runtime input |
| parseLiteral(ast) | Client → Server (inline) | Validate AST literal |
Example: Custom DateTime scalar
import { GraphQLScalarType, Kind } from "graphql";
export const DateTime = new GraphQLScalarType({
name: "DateTime",
description: "ISO-8601 date-time string",
serialize: (v) => (v instanceof Date ? v.toISOString() : v),
parseValue: (v) => new Date(v),
parseLiteral: (ast) =>
ast.kind === Kind.STRING ? new Date(ast.value) : null
});
3. Implementing Scalar Serialization
| Aspect | Detail |
| Output | Must return a JSON-serializable value |
| Errors | Throw to fail field with execution error |
| Idempotent | Same input → same output |
4. Implementing Scalar Parsing
| Hook | Receives | Returns |
| parseValue | JSON value from variables | Internal representation |
| parseLiteral | AST node (Kind.STRING/INT/...) | Internal representation |
Warning: Always implement BOTH parseValue and parseLiteral, otherwise inline literals or variables may silently fail.
5. Validating Scalar Values
import { GraphQLError } from "graphql";
parseValue(value) {
if (typeof value !== "string" || !/^\\+?[1-9]\\d{1,14}$/.test(value)) {
throw new GraphQLError("Invalid E.164 phone number");
}
return value;
}
| Strategy | Use |
| Regex | Format-bound (phone, slug, hex) |
| Library | Email, URL, UUID, JWT — use proven libs |
| Range | NonNegativeInt, Positive, BigInt |
6. Creating Date Scalar
| Variant | Format | Library |
| DateTime | ISO-8601 with offset | graphql-scalars |
| Date | YYYY-MM-DD | graphql-scalars |
| Time | HH:MM:SS[.sss] | graphql-scalars |
| Timestamp | Unix epoch seconds | custom |
7. Creating JSON Scalar
| Concern | Note |
| Use case | Schemaless blobs (analytics events, settings) |
| Library | graphql-type-json |
| Risk | Loses type safety; avoid for first-class data |
8. Creating Email Scalar
Example: EmailAddress via graphql-scalars
import { EmailAddressTypeDefinition, EmailAddressResolver } from "graphql-scalars";
const typeDefs = [EmailAddressTypeDefinition, /* ... */];
const resolvers = { EmailAddress: EmailAddressResolver };
| Validation | Standard |
| Format | RFC 5321 / 5322 |
| Library | graphql-scalars EmailAddress |
9. Creating URL Scalar
| Concern | Detail |
| Validation | WHATWG URL, allowed schemes (http/https) |
| Type | URL from graphql-scalars |
| Security | Reject javascript:, file: schemes server-side |
10. Creating Upload Scalar
| Aspect | Detail |
| Spec | graphql-multipart-request-spec |
| Library | graphql-upload |
| Resolver receives | { filename, mimetype, encoding, createReadStream() } |
| Alternative | Pre-signed S3 URLs (recommended for large files) |