0
# Code Generation
1
2
Structure-based API for creating new TypeScript code elements with full type safety and intelligent formatting. The structure system provides a declarative way to generate code without manually constructing AST nodes.
3
4
## Capabilities
5
6
### Structure Interfaces
7
8
Base interfaces that define the shape of code elements to be generated.
9
10
```typescript { .api }
11
enum StructureKind {
12
ImportAttribute,
13
CallSignature,
14
Class,
15
ClassStaticBlock,
16
ConstructSignature,
17
Constructor,
18
ConstructorOverload,
19
Decorator,
20
Enum,
21
EnumMember,
22
ExportAssignment,
23
ExportDeclaration,
24
ExportSpecifier,
25
Function,
26
FunctionOverload,
27
GetAccessor,
28
ImportDeclaration,
29
ImportSpecifier,
30
IndexSignature,
31
Interface,
32
JsxAttribute,
33
JsxSpreadAttribute,
34
JsxElement,
35
JsxSelfClosingElement,
36
JSDoc,
37
JSDocTag,
38
Method,
39
MethodOverload,
40
MethodSignature,
41
Module,
42
Parameter,
43
Property,
44
PropertyAssignment,
45
PropertySignature,
46
SetAccessor,
47
ShorthandPropertyAssignment,
48
SourceFile,
49
SpreadAssignment,
50
TypeAlias,
51
TypeParameter,
52
VariableDeclaration,
53
VariableStatement,
54
}
55
56
interface Structure {
57
kind: StructureKind;
58
}
59
60
interface StatementedNodeStructure {
61
statements?: (string | WriterFunction | StatementStructures)[];
62
}
63
64
interface JSDocableNodeStructure {
65
docs?: (JSDocStructure | string)[];
66
}
67
68
interface DecoratableNodeStructure {
69
decorators?: DecoratorStructure[];
70
}
71
```
72
73
### Class Generation Structures
74
75
Structures for generating class-related code elements.
76
77
```typescript { .api }
78
interface ClassDeclarationStructure extends Structure, JSDocableNodeStructure, DecoratableNodeStructure {
79
kind: StructureKind.Class;
80
name: string;
81
extends?: string;
82
implements?: string[];
83
typeParameters?: TypeParameterDeclarationStructure[];
84
isAbstract?: boolean;
85
isExported?: boolean;
86
isDefaultExport?: boolean;
87
constructors?: ConstructorDeclarationStructure[];
88
properties?: PropertyDeclarationStructure[];
89
methods?: MethodDeclarationStructure[];
90
getAccessors?: GetAccessorDeclarationStructure[];
91
setAccessors?: SetAccessorDeclarationStructure[];
92
}
93
94
interface PropertyDeclarationStructure extends Structure, JSDocableNodeStructure, DecoratableNodeStructure {
95
kind: StructureKind.Property;
96
name: string;
97
type?: string;
98
initializer?: string | WriterFunction;
99
hasQuestionToken?: boolean;
100
hasExclamationToken?: boolean;
101
isReadonly?: boolean;
102
isStatic?: boolean;
103
scope?: Scope;
104
}
105
106
interface MethodDeclarationStructure extends Structure, JSDocableNodeStructure, DecoratableNodeStructure {
107
kind: StructureKind.Method;
108
name: string;
109
parameters?: ParameterDeclarationStructure[];
110
returnType?: string;
111
typeParameters?: TypeParameterDeclarationStructure[];
112
statements?: (string | WriterFunction)[];
113
isAbstract?: boolean;
114
isAsync?: boolean;
115
isGenerator?: boolean;
116
isStatic?: boolean;
117
scope?: Scope;
118
overloads?: MethodDeclarationOverloadStructure[];
119
}
120
121
interface ConstructorDeclarationStructure extends Structure, JSDocableNodeStructure {
122
kind: StructureKind.Constructor;
123
parameters?: ParameterDeclarationStructure[];
124
statements?: (string | WriterFunction)[];
125
scope?: Scope;
126
overloads?: ConstructorDeclarationOverloadStructure[];
127
}
128
129
enum Scope {
130
Public = "public",
131
Protected = "protected",
132
Private = "private",
133
}
134
```
135
136
### Function Generation Structures
137
138
```typescript { .api }
139
interface FunctionDeclarationStructure extends Structure, JSDocableNodeStructure, StatementedNodeStructure {
140
kind: StructureKind.Function;
141
name: string;
142
parameters?: ParameterDeclarationStructure[];
143
returnType?: string;
144
typeParameters?: TypeParameterDeclarationStructure[];
145
isAsync?: boolean;
146
isGenerator?: boolean;
147
isExported?: boolean;
148
isDefaultExport?: boolean;
149
overloads?: FunctionDeclarationOverloadStructure[];
150
}
151
152
interface ParameterDeclarationStructure extends Structure, DecoratableNodeStructure {
153
kind: StructureKind.Parameter;
154
name: string;
155
type?: string;
156
initializer?: string | WriterFunction;
157
hasQuestionToken?: boolean;
158
isRestParameter?: boolean;
159
scope?: Scope;
160
}
161
```
162
163
### Interface Generation Structures
164
165
```typescript { .api }
166
interface InterfaceDeclarationStructure extends Structure, JSDocableNodeStructure {
167
kind: StructureKind.Interface;
168
name: string;
169
extends?: string[];
170
typeParameters?: TypeParameterDeclarationStructure[];
171
isExported?: boolean;
172
isDefaultExport?: boolean;
173
properties?: PropertySignatureStructure[];
174
methods?: MethodSignatureStructure[];
175
callSignatures?: CallSignatureDeclarationStructure[];
176
constructSignatures?: ConstructSignatureDeclarationStructure[];
177
indexSignatures?: IndexSignatureDeclarationStructure[];
178
}
179
180
interface PropertySignatureStructure extends Structure, JSDocableNodeStructure {
181
kind: StructureKind.PropertySignature;
182
name: string;
183
type?: string;
184
hasQuestionToken?: boolean;
185
isReadonly?: boolean;
186
}
187
188
interface MethodSignatureStructure extends Structure, JSDocableNodeStructure {
189
kind: StructureKind.MethodSignature;
190
name: string;
191
parameters?: ParameterDeclarationStructure[];
192
returnType?: string;
193
typeParameters?: TypeParameterDeclarationStructure[];
194
hasQuestionToken?: boolean;
195
}
196
```
197
198
### Import and Export Structures
199
200
```typescript { .api }
201
interface ImportDeclarationStructure extends Structure {
202
kind: StructureKind.ImportDeclaration;
203
moduleSpecifier: string;
204
defaultImport?: string;
205
namespaceImport?: string;
206
namedImports?: (string | ImportSpecifierStructure)[];
207
isTypeOnly?: boolean;
208
}
209
210
interface ImportSpecifierStructure {
211
name: string;
212
alias?: string;
213
isTypeOnly?: boolean;
214
}
215
216
interface ExportDeclarationStructure extends Structure {
217
kind: StructureKind.ExportDeclaration;
218
moduleSpecifier?: string;
219
namedExports?: (string | ExportSpecifierStructure)[];
220
namespaceExport?: string;
221
isTypeOnly?: boolean;
222
}
223
224
interface ExportSpecifierStructure {
225
name: string;
226
alias?: string;
227
isTypeOnly?: boolean;
228
}
229
```
230
231
### Variable and Type Structures
232
233
```typescript { .api }
234
interface VariableStatementStructure extends Structure, JSDocableNodeStructure {
235
kind: StructureKind.VariableStatement;
236
declarationKind: VariableDeclarationKind;
237
declarations: VariableDeclarationStructure[];
238
isExported?: boolean;
239
isDefaultExport?: boolean;
240
}
241
242
interface VariableDeclarationStructure {
243
name: string;
244
type?: string;
245
initializer?: string | WriterFunction;
246
}
247
248
interface TypeAliasDeclarationStructure extends Structure, JSDocableNodeStructure {
249
kind: StructureKind.TypeAlias;
250
name: string;
251
type: string;
252
typeParameters?: TypeParameterDeclarationStructure[];
253
isExported?: boolean;
254
isDefaultExport?: boolean;
255
}
256
257
interface EnumDeclarationStructure extends Structure, JSDocableNodeStructure {
258
kind: StructureKind.Enum;
259
name: string;
260
members: EnumMemberStructure[];
261
isConst?: boolean;
262
isExported?: boolean;
263
isDefaultExport?: boolean;
264
}
265
266
interface EnumMemberStructure extends Structure, JSDocableNodeStructure {
267
name: string;
268
value?: string | number;
269
}
270
```
271
272
### Code Block Writer
273
274
Utility for generating formatted code with proper indentation and structure.
275
276
```typescript { .api }
277
class CodeBlockWriter {
278
/** Write text */
279
write(text: string): this;
280
281
/** Write a line of text */
282
writeLine(text?: string): this;
283
284
/** Write a new line */
285
newLine(): this;
286
287
/** Write spaces for current indentation level */
288
indent(): this;
289
290
/** Increase indentation level */
291
indentBlock(): this;
292
293
/** Write text within a block with increased indentation */
294
inlineBlock(block: () => void): this;
295
296
/** Write a code block with braces and proper indentation */
297
block(block?: () => void): this;
298
299
/** Conditionally write text */
300
conditionalWrite(condition: boolean, text: string): this;
301
302
/** Get the current indentation level */
303
getIndentationLevel(): number;
304
305
/** Set the indentation level */
306
setIndentationLevel(indentationLevel: number): this;
307
308
/** Get the generated string */
309
toString(): string;
310
}
311
312
type WriterFunction = (writer: CodeBlockWriter) => void;
313
```
314
315
### Writers Utility Class
316
317
Static utility class providing common writer functions for code generation.
318
319
```typescript { .api }
320
class Writers {
321
/** Create a writer function for object properties */
322
static object(obj: { [key: string]: string | WriterFunction }): WriterFunction;
323
324
/** Create a writer function for array elements */
325
static array(elements: (string | WriterFunction)[]): WriterFunction;
326
327
/** Create a writer function for union types */
328
static unionType(types: string[]): WriterFunction;
329
330
/** Create a writer function for intersection types */
331
static intersectionType(types: string[]): WriterFunction;
332
333
/** Create a writer function for conditional expressions */
334
static conditionalExpression(condition: string, whenTrue: string, whenFalse: string): WriterFunction;
335
336
/** Create a writer function for assertions */
337
static assertion(type: string, expr: string): WriterFunction;
338
}
339
340
type WriterFunctionOrValue = string | WriterFunction;
341
```
342
343
**Usage Examples:**
344
345
```typescript
346
import { Project, StructureKind, Scope, VariableDeclarationKind } from "ts-morph";
347
348
const project = new Project();
349
const sourceFile = project.createSourceFile("generated.ts", "");
350
351
// Generate a class
352
const classDeclaration = sourceFile.addClass({
353
kind: StructureKind.Class,
354
name: "UserService",
355
isExported: true,
356
properties: [
357
{
358
kind: StructureKind.Property,
359
name: "users",
360
type: "User[]",
361
scope: Scope.Private,
362
initializer: "[]",
363
},
364
],
365
constructors: [
366
{
367
kind: StructureKind.Constructor,
368
parameters: [
369
{
370
kind: StructureKind.Parameter,
371
name: "apiClient",
372
type: "ApiClient",
373
scope: Scope.Private,
374
},
375
],
376
statements: ["// Constructor implementation"],
377
},
378
],
379
methods: [
380
{
381
kind: StructureKind.Method,
382
name: "getUsers",
383
returnType: "Promise<User[]>",
384
isAsync: true,
385
statements: [
386
"const response = await this.apiClient.get('/users');",
387
"return response.data;",
388
],
389
},
390
{
391
kind: StructureKind.Method,
392
name: "createUser",
393
parameters: [
394
{
395
kind: StructureKind.Parameter,
396
name: "userData",
397
type: "CreateUserData",
398
},
399
],
400
returnType: "Promise<User>",
401
isAsync: true,
402
statements: [
403
"const response = await this.apiClient.post('/users', userData);",
404
"return response.data;",
405
],
406
},
407
],
408
});
409
410
// Generate an interface
411
sourceFile.addInterface({
412
kind: StructureKind.Interface,
413
name: "User",
414
isExported: true,
415
properties: [
416
{
417
kind: StructureKind.PropertySignature,
418
name: "id",
419
type: "string",
420
},
421
{
422
kind: StructureKind.PropertySignature,
423
name: "name",
424
type: "string",
425
},
426
{
427
kind: StructureKind.PropertySignature,
428
name: "email",
429
type: "string",
430
},
431
{
432
kind: StructureKind.PropertySignature,
433
name: "age",
434
type: "number",
435
hasQuestionToken: true,
436
},
437
],
438
});
439
440
// Generate a type alias
441
sourceFile.addTypeAlias({
442
kind: StructureKind.TypeAlias,
443
name: "CreateUserData",
444
type: "Omit<User, 'id'>",
445
isExported: true,
446
});
447
448
// Generate imports
449
sourceFile.addImportDeclaration({
450
kind: StructureKind.ImportDeclaration,
451
moduleSpecifier: "./api-client",
452
namedImports: ["ApiClient"],
453
});
454
455
// Generate an enum
456
sourceFile.addEnum({
457
kind: StructureKind.Enum,
458
name: "UserRole",
459
isExported: true,
460
members: [
461
{ name: "Admin", value: "'admin'" },
462
{ name: "User", value: "'user'" },
463
{ name: "Guest", value: "'guest'" },
464
],
465
});
466
467
// Generate variables
468
sourceFile.addVariableStatement({
469
kind: StructureKind.VariableStatement,
470
declarationKind: VariableDeclarationKind.Const,
471
isExported: true,
472
declarations: [
473
{
474
name: "DEFAULT_USER_ROLE",
475
type: "UserRole",
476
initializer: "UserRole.User",
477
},
478
],
479
});
480
481
console.log(sourceFile.getFullText());
482
```
483
484
**Advanced Code Generation with Writers:**
485
486
```typescript
487
import { Project, Writers } from "ts-morph";
488
489
const project = new Project();
490
const sourceFile = project.createSourceFile("complex.ts", "");
491
492
// Using writer functions for complex code generation
493
sourceFile.addFunction({
494
name: "createValidator",
495
returnType: "ValidationFunction",
496
isExported: true,
497
parameters: [
498
{
499
name: "schema",
500
type: "ValidationSchema",
501
},
502
],
503
statements: [
504
(writer) => {
505
writer.writeLine("return (data: any) => {");
506
writer.indent().writeLine("const errors: string[] = [];");
507
writer.newLine();
508
writer.writeLine("// Validation logic here");
509
writer.newLine();
510
writer.writeLine("return {");
511
writer.indent().writeLine("isValid: errors.length === 0,");
512
writer.writeLine("errors");
513
writer.outdent().writeLine("};");
514
writer.outdent().writeLine("};");
515
},
516
],
517
});
518
519
// Using Writers utility methods
520
sourceFile.addTypeAlias({
521
name: "ComplexType",
522
type: Writers.unionType([
523
"string",
524
"number",
525
Writers.object({
526
name: "string",
527
age: "number",
528
}).toString(),
529
]).toString(),
530
isExported: true,
531
});
532
```