0
# Type System and Utilities
1
2
Type transformation utilities, custom scalar definitions, and helper functions for creating complex GraphQL types. This module provides powerful tools for manipulating GraphQL types, creating unions and enums, and extending the GraphQL type system with custom scalars.
3
4
## Capabilities
5
6
### Type Transformation Utilities
7
8
Helper functions for creating derivative types from existing GraphQL types, similar to TypeScript utility types.
9
10
```typescript { .api }
11
/**
12
* Creates a partial version of a GraphQL type where all fields are optional
13
* @param classRef - Reference to the base class
14
* @param decorator - Optional decorator to apply to the new type
15
* @returns New type class with all optional fields
16
*/
17
function PartialType<T>(
18
classRef: Type<T>,
19
decorator?: ClassDecorator
20
): Type<Partial<T>>;
21
22
/**
23
* Creates a new type with only selected fields from the base type
24
* @param classRef - Reference to the base class
25
* @param keys - Array of field names to include
26
* @param decorator - Optional decorator to apply to the new type
27
* @returns New type class with only selected fields
28
*/
29
function PickType<T, K extends keyof T>(
30
classRef: Type<T>,
31
keys: readonly K[],
32
decorator?: ClassDecorator
33
): Type<Pick<T, K>>;
34
35
/**
36
* Creates a new type with specified fields omitted from the base type
37
* @param classRef - Reference to the base class
38
* @param keys - Array of field names to omit
39
* @param decorator - Optional decorator to apply to the new type
40
* @returns New type class with omitted fields removed
41
*/
42
function OmitType<T, K extends keyof T>(
43
classRef: Type<T>,
44
keys: readonly K[],
45
decorator?: ClassDecorator
46
): Type<Omit<T, K>>;
47
48
/**
49
* Creates an intersection type combining fields from two types
50
* @param classARef - Reference to the first class
51
* @param classBRef - Reference to the second class
52
* @param decorator - Optional decorator to apply to the new type
53
* @returns New type class combining both input types
54
*/
55
function IntersectionType<A, B>(
56
classARef: Type<A>,
57
classBRef: Type<B>,
58
decorator?: ClassDecorator
59
): Type<A & B>;
60
```
61
62
**Usage Examples:**
63
64
```typescript
65
import { ObjectType, InputType, Field, PartialType, PickType, OmitType, IntersectionType } from "@nestjs/graphql";
66
67
// Base types
68
@ObjectType()
69
class User {
70
@Field()
71
id: string;
72
73
@Field()
74
name: string;
75
76
@Field()
77
email: string;
78
79
@Field()
80
createdAt: Date;
81
}
82
83
@InputType()
84
class CreateUserInput {
85
@Field()
86
name: string;
87
88
@Field()
89
email: string;
90
91
@Field({ nullable: true })
92
bio?: string;
93
}
94
95
// Partial type - all fields optional
96
@InputType()
97
class UpdateUserInput extends PartialType(CreateUserInput) {}
98
// Results in: { name?: string; email?: string; bio?: string; }
99
100
// Pick type - select specific fields
101
@ObjectType()
102
class UserSummary extends PickType(User, ['id', 'name'] as const) {}
103
// Results in: { id: string; name: string; }
104
105
// Omit type - exclude specific fields
106
@ObjectType()
107
class PublicUser extends OmitType(User, ['email'] as const) {}
108
// Results in: { id: string; name: string; createdAt: Date; }
109
110
// Intersection type - combine multiple types
111
@InputType()
112
class UserPreferences {
113
@Field()
114
theme: string;
115
116
@Field()
117
notifications: boolean;
118
}
119
120
@InputType()
121
class UserWithPreferences extends IntersectionType(
122
CreateUserInput,
123
UserPreferences
124
) {}
125
// Results in: CreateUserInput & UserPreferences combined
126
```
127
128
### Union and Enum Type Creation
129
130
Functions for creating GraphQL union types and registering TypeScript enums as GraphQL enums.
131
132
```typescript { .api }
133
/**
134
* Creates a GraphQL union type from multiple object types
135
* @param options - Configuration options for the union type
136
* @returns GraphQL union type definition
137
*/
138
function createUnionType(options: UnionOptions): GraphQLUnionType;
139
140
/**
141
* Registers a TypeScript enum as a GraphQL enum type
142
* @param enumObject - The TypeScript enum object to register
143
* @param options - Configuration options for the enum type
144
*/
145
function registerEnumType(enumObject: object, options: EnumOptions): void;
146
147
/**
148
* Options for creating union types
149
*/
150
interface UnionOptions {
151
/** Name of the union type */
152
name: string;
153
/** Array of types that can be part of the union */
154
types: () => readonly [Function, ...Function[]];
155
/** Function to resolve which concrete type an object represents */
156
resolveType?: (value: any) => Function | string | Promise<Function | string>;
157
/** Description for the union type */
158
description?: string;
159
}
160
161
/**
162
* Options for registering enum types
163
*/
164
interface EnumOptions {
165
/** Name of the GraphQL enum type */
166
name: string;
167
/** Description for the enum type */
168
description?: string;
169
/** Custom values mapping for enum entries */
170
valuesMap?: Record<string, EnumValueConfig>;
171
}
172
173
interface EnumValueConfig {
174
/** Custom value for the enum entry */
175
value?: any;
176
/** Description for the enum entry */
177
description?: string;
178
/** Deprecation reason */
179
deprecationReason?: string;
180
}
181
```
182
183
**Usage Examples:**
184
185
```typescript
186
import { ObjectType, Field, createUnionType, registerEnumType } from "@nestjs/graphql";
187
188
// Define types for union
189
@ObjectType()
190
class User {
191
@Field()
192
id: string;
193
194
@Field()
195
name: string;
196
}
197
198
@ObjectType()
199
class Post {
200
@Field()
201
id: string;
202
203
@Field()
204
title: string;
205
}
206
207
// Create union type
208
const SearchResult = createUnionType({
209
name: 'SearchResult',
210
types: () => [User, Post] as const,
211
resolveType: (value) => {
212
if (value.name) return User;
213
if (value.title) return Post;
214
return null;
215
},
216
});
217
218
// TypeScript enum
219
enum UserRole {
220
ADMIN = 'admin',
221
USER = 'user',
222
MODERATOR = 'moderator',
223
}
224
225
// Register enum with GraphQL
226
registerEnumType(UserRole, {
227
name: 'UserRole',
228
description: 'User role in the system',
229
valuesMap: {
230
ADMIN: {
231
description: 'System administrator with full access',
232
},
233
USER: {
234
description: 'Regular user with limited access',
235
},
236
MODERATOR: {
237
description: 'Content moderator with intermediate access',
238
deprecationReason: 'Use ADMIN role instead',
239
},
240
},
241
});
242
243
// Usage in GraphQL types
244
@ObjectType()
245
class User {
246
@Field()
247
id: string;
248
249
@Field(() => UserRole)
250
role: UserRole;
251
}
252
```
253
254
### Built-in Scalar Types
255
256
Pre-defined GraphQL scalar types for common data formats.
257
258
```typescript { .api }
259
/**
260
* GraphQL scalar type for ISO 8601 DateTime strings
261
* Serializes JavaScript Date objects to ISO string format
262
*/
263
export const GraphQLISODateTime: GraphQLScalarType;
264
265
/**
266
* GraphQL scalar type for Unix timestamps
267
* Serializes JavaScript Date objects to Unix timestamp numbers
268
*/
269
export const GraphQLTimestamp: GraphQLScalarType;
270
271
/**
272
* GraphQL Int scalar type (re-export from graphql package)
273
*/
274
export const Int: GraphQLScalarType;
275
276
/**
277
* GraphQL Float scalar type (re-export from graphql package)
278
*/
279
export const Float: GraphQLScalarType;
280
281
/**
282
* GraphQL ID scalar type (re-export from graphql package)
283
*/
284
export const ID: GraphQLScalarType;
285
```
286
287
**Usage Examples:**
288
289
```typescript
290
import { ObjectType, Field, GraphQLISODateTime, GraphQLTimestamp, Int, Float, ID } from "@nestjs/graphql";
291
292
@ObjectType()
293
class Event {
294
@Field(() => ID)
295
id: string;
296
297
@Field()
298
title: string;
299
300
@Field(() => GraphQLISODateTime)
301
createdAt: Date; // Serialized as "2023-12-01T10:30:00.000Z"
302
303
@Field(() => GraphQLTimestamp)
304
updatedAt: Date; // Serialized as 1701423000000
305
306
@Field(() => Int)
307
attendeeCount: number;
308
309
@Field(() => Float)
310
rating: number;
311
}
312
```
313
314
### Custom Scalar Creation
315
316
Tools for creating custom GraphQL scalar types with validation and serialization.
317
318
```typescript { .api }
319
/**
320
* Interface for implementing custom GraphQL scalars
321
*/
322
interface GraphQLScalarTypeConfig<TInternal, TExternal> {
323
name: string;
324
description?: string;
325
326
/** Serialize internal value to external representation */
327
serialize(value: TInternal): TExternal;
328
329
/** Parse external value from variables */
330
parseValue(value: TExternal): TInternal;
331
332
/** Parse external value from AST literal */
333
parseLiteral(ast: ValueNode, variables?: Record<string, any>): TInternal;
334
}
335
336
/**
337
* Base class for implementing custom scalars with the @Scalar decorator
338
*/
339
abstract class CustomScalar<T, K> {
340
/** Human-readable description of the scalar */
341
description?: string;
342
343
/** Serialize internal value to external representation */
344
abstract serialize(value: T): K;
345
346
/** Parse external value from GraphQL variables */
347
abstract parseValue(value: K): T;
348
349
/** Parse external value from AST literal in queries */
350
abstract parseLiteral(ast: ValueNode): T;
351
}
352
```
353
354
**Custom Scalar Examples:**
355
356
```typescript
357
import { Scalar, CustomScalar } from "@nestjs/graphql";
358
import { GraphQLError } from "graphql";
359
import { ValueNode, Kind } from "graphql/language";
360
361
// Email scalar with validation
362
@Scalar('Email', () => String)
363
export class EmailScalar implements CustomScalar<string, string> {
364
description = 'Email custom scalar type';
365
366
serialize(value: string): string {
367
if (!this.isValidEmail(value)) {
368
throw new GraphQLError('Value must be a valid email address');
369
}
370
return value;
371
}
372
373
parseValue(value: string): string {
374
if (!this.isValidEmail(value)) {
375
throw new GraphQLError('Value must be a valid email address');
376
}
377
return value;
378
}
379
380
parseLiteral(ast: ValueNode): string {
381
if (ast.kind !== Kind.STRING) {
382
throw new GraphQLError('Email must be a string');
383
}
384
385
if (!this.isValidEmail(ast.value)) {
386
throw new GraphQLError('Value must be a valid email address');
387
}
388
389
return ast.value;
390
}
391
392
private isValidEmail(email: string): boolean {
393
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
394
return emailRegex.test(email);
395
}
396
}
397
398
// URL scalar
399
@Scalar('URL', () => String)
400
export class URLScalar implements CustomScalar<string, string> {
401
description = 'URL custom scalar type';
402
403
serialize(value: string): string {
404
return this.validateURL(value);
405
}
406
407
parseValue(value: string): string {
408
return this.validateURL(value);
409
}
410
411
parseLiteral(ast: ValueNode): string {
412
if (ast.kind !== Kind.STRING) {
413
throw new GraphQLError('URL must be a string');
414
}
415
return this.validateURL(ast.value);
416
}
417
418
private validateURL(url: string): string {
419
try {
420
new URL(url);
421
return url;
422
} catch {
423
throw new GraphQLError('Value must be a valid URL');
424
}
425
}
426
}
427
428
// Usage in types
429
@ObjectType()
430
class User {
431
@Field()
432
id: string;
433
434
@Field(() => EmailScalar)
435
email: string;
436
437
@Field(() => URLScalar, { nullable: true })
438
website?: string;
439
}
440
```
441
442
### Type Helper Interfaces
443
444
Utility interfaces and types for advanced type manipulation.
445
446
```typescript { .api }
447
/**
448
* Helper type for field definitions
449
*/
450
type FieldType = string | number | boolean | Date | any[];
451
452
/**
453
* Type reference for GraphQL schema elements
454
*/
455
type GqlTypeReference = Function | object | symbol | [Function | object | symbol];
456
457
/**
458
* Class type reference with constructor
459
*/
460
type Type<T = any> = new (...args: any[]) => T;
461
462
/**
463
* Function type for defining return types in decorators
464
*/
465
type ReturnTypeFunc = (returns?: void) => Function | object | symbol;
466
467
/**
468
* Type for class decorators that can be applied to GraphQL types
469
*/
470
type ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void;
471
472
/**
473
* Options for scalar type mappings in schema building
474
*/
475
interface ScalarsTypeMap {
476
/** TypeScript/JavaScript type constructor */
477
type: Function;
478
/** Corresponding GraphQL scalar type */
479
scalar: GraphQLScalarType;
480
}
481
482
/**
483
* Configuration for complexity analysis
484
*/
485
interface Complexity {
486
/** Maximum query complexity allowed */
487
maximumComplexity: number;
488
/** Custom complexity function */
489
createComplexityLimitRule?: (maximumComplexity: number) => any;
490
}
491
```