Types — Scalars, Enums & Interfaces
GraphQL has a rich type system beyond simple Object Types. Scalars represent leaf values, Enums constrain string options, Interfaces define shared fields across types, and Unions group heterogeneous types.
1 Built-in & Custom Scalars
GraphQL SDL — Scalars
# Built-in scalars
# Int, Float, String, Boolean, ID
# Custom scalars (require resolver implementations)
scalar DateTime # ISO 8601 date string
scalar Email # Validated email address
scalar URL # Valid URL string
scalar JSON # Arbitrary JSON blob
scalar Upload # File upload
type User {
id: ID!
email: Email!
website: URL
createdAt: DateTime!
metadata: JSON
}
# Scalar resolver (Node.js)
const { GraphQLScalarType, Kind } = require("graphql");
const DateTimeScalar = new GraphQLScalarType({
name: "DateTime",
serialize: (value) => new Date(value).toISOString(),
parseValue: (value) => new Date(value),
parseLiteral: (ast) => {
if (ast.kind === Kind.STRING) return new Date(ast.value);
return null;
}
});
2 Interfaces & Unions
GraphQL SDL — Interface & Union
# Interface — shared contract
interface Node {
id: ID!
}
interface Timestamped {
createdAt: DateTime!
updatedAt: DateTime!
}
type User implements Node & Timestamped {
id: ID!
name: String!
createdAt: DateTime!
updatedAt: DateTime!
}
type Post implements Node & Timestamped {
id: ID!
title: String!
createdAt: DateTime!
updatedAt: DateTime!
}
# Union — completely different types
union SearchResult = User | Post | Product
type Query {
node(id: ID!): Node # Returns any Node implementor
search(q: String!): [SearchResult!]!
}
# __resolveType is required for interfaces and unions
const resolvers = {
SearchResult: {
__resolveType: (obj) => {
if (obj.email) return "User";
if (obj.title) return "Post";
if (obj.price) return "Product";
return null;
}
}
};
3 Code Challenge
Challenge: Design a notification system schema using an interface:
interface Notification { id: ID!, createdAt: DateTime!, read: Boolean! } with three implementing types: CommentNotification, FollowNotification, and MentionNotification. Each should have type-specific fields.