or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

federation.mdindex.mdmodule-configuration.mdresolvers.mdschema-building.mdschema-decorators.mdservices.mdsubscriptions.mdtype-system.md

type-system.mddocs/

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

```