NestJS — Enterprise Node.js

GraphQL Advanced Types: Scalars, Directives, Interfaces & Unions

18 min Lesson 64 of 80

GraphQL Advanced Types: Scalars, Directives, Interfaces & Unions

Real GraphQL schemas need more than object types. Custom scalars model values such as DateTime and Money, directives attach schema-level behavior, interfaces describe shared fields, and unions return one of several object shapes.

Core idea

This feature is about controlling how the application is organized and how it behaves at runtime. These are the points a developer should understand before using it in a real project:

  • Custom scalars must parse client input, serialize server output, and validate the value boundary carefully.
  • Directives can annotate schema fields for behaviors such as auth hints, formatting, or federation metadata.
  • Interfaces work when several object types share fields and clients can query the common shape.
  • Unions are useful for search results or polymorphic responses where members do not share enough fields.
  • ResolveType logic must be deterministic so clients receive correct __typename values.

Practical example

The following example shows the idea in a practical NestJS project. The goal is not to memorize the snippet, but to understand where it belongs in the architecture:

@Scalar('DateTime', () => Date) export class DateTimeScalar implements CustomScalar<string, Date> { parseValue(value: string): Date { return new Date(value); } serialize(value: Date): string { return value.toISOString(); } parseLiteral(ast: ValueNode): Date | null { return ast.kind === Kind.STRING ? new Date(ast.value) : null; } } export const SearchResultUnion = createUnionType({ name: 'SearchResult', types: () => [User, Article] as const, resolveType(value) { return 'email' in value ? User : Article; }, });
Design note: Advanced GraphQL types are part of API design, not decoration. They help clients understand the exact shape and semantics of data before runtime.

Production checklist

  • Validate scalar boundaries strictly.
  • Keep directive behavior documented for frontend teams.
  • Prefer interfaces when types share a common contract.
  • Use unions when the result can be one of several unrelated shapes.
Rule of thumb: If the feature makes boundaries clearer and tests easier, it is probably the right choice. If it hides dependencies or makes tracing harder, redesign.

Summary

This lesson covers an advanced NestJS area that matters when building enterprise applications. Focus on clear boundaries, testable behavior, and choosing the right tool for the context instead of using every feature everywhere.