0
# Type System Integration
1
2
Direct access to TypeScript's type checker and type information for advanced static analysis and type-aware transformations. This enables sophisticated analysis of TypeScript code beyond syntax-level operations.
3
4
## Capabilities
5
6
### Type Checker
7
8
The TypeScript type checker provides comprehensive type analysis capabilities.
9
10
```typescript { .api }
11
class TypeChecker {
12
/** Get the type of a node at its location */
13
getTypeAtLocation(node: Node): Type;
14
15
/** Get the symbol at a specific location */
16
getSymbolAtLocation(node: Node): Symbol | undefined;
17
18
/** Get the type of a symbol at a specific location */
19
getTypeOfSymbolAtLocation(symbol: Symbol, node: Node): Type;
20
21
/** Get the apparent type (after applying type arguments) */
22
getApparentType(type: Type): Type;
23
24
/** Get the base type of a type */
25
getBaseTypeOfLiteralType(type: Type): Type;
26
27
/** Get the full type of a node (including contextual type) */
28
getFullTypeAtLocation(node: Node): Type;
29
30
/** Get the contextual type for an expression */
31
getContextualType(node: Expression): Type | undefined;
32
33
/** Get the signature from a declaration */
34
getSignatureFromDeclaration(node: SignatureDeclaration): Signature | undefined;
35
36
/** Get all signatures for a type */
37
getSignaturesOfType(type: Type, kind: SignatureKind): Signature[];
38
39
/** Get the return type of a signature */
40
getReturnTypeOfSignature(signature: Signature): Type;
41
42
/** Check if types are assignable */
43
isTypeAssignableTo(source: Type, target: Type): boolean;
44
45
/** Get exports of a module */
46
getExportsOfModule(moduleSymbol: Symbol): Symbol[];
47
48
/** Get properties of a type */
49
getPropertiesOfType(type: Type): Symbol[];
50
51
/** Get all accessible symbols at location */
52
getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[];
53
}
54
55
enum SignatureKind {
56
Call = 0,
57
Construct = 1,
58
}
59
```
60
61
### Type Class
62
63
Represents a TypeScript type with comprehensive type information and analysis methods.
64
65
```typescript { .api }
66
class Type {
67
/** Get the string representation of the type */
68
getText(enclosingNode?: Node, typeFormatFlags?: TypeFormatFlags): string;
69
70
/** Get the symbol associated with this type */
71
getSymbol(): Symbol | undefined;
72
73
/** Get the apparent type (after type argument substitution) */
74
getApparentType(): Type;
75
76
/** Get constraint of a type parameter */
77
getConstraint(): Type | undefined;
78
79
/** Get default type of a type parameter */
80
getDefault(): Type | undefined;
81
82
/** Get union types if this is a union type */
83
getUnionTypes(): Type[];
84
85
/** Get intersection types if this is an intersection type */
86
getIntersectionTypes(): Type[];
87
88
/** Get type arguments if this is a generic type instance */
89
getTypeArguments(): Type[];
90
91
/** Get call signatures */
92
getCallSignatures(): Signature[];
93
94
/** Get construct signatures */
95
getConstructSignatures(): Signature[];
96
97
/** Get array element type if this is an array type */
98
getArrayElementType(): Type | undefined;
99
100
/** Get number index type */
101
getNumberIndexType(): Type | undefined;
102
103
/** Get string index type */
104
getStringIndexType(): Type | undefined;
105
106
/** Get base types */
107
getBaseTypes(): Type[];
108
109
/** Check if this is an array type */
110
isArray(): boolean;
111
112
/** Check if this is a boolean type */
113
isBoolean(): boolean;
114
115
/** Check if this is a string type */
116
isString(): boolean;
117
118
/** Check if this is a number type */
119
isNumber(): boolean;
120
121
/** Check if this is a literal type */
122
isLiteral(): boolean;
123
124
/** Check if this is a boolean literal type */
125
isBooleanLiteral(): boolean;
126
127
/** Check if this is an enum literal type */
128
isEnumLiteral(): boolean;
129
130
/** Check if this is a number literal type */
131
isNumberLiteral(): boolean;
132
133
/** Check if this is a string literal type */
134
isStringLiteral(): boolean;
135
136
/** Check if this is a class type */
137
isClass(): boolean;
138
139
/** Check if this is a class or interface type */
140
isClassOrInterface(): boolean;
141
142
/** Check if this is an enum type */
143
isEnum(): boolean;
144
145
/** Check if this is an interface type */
146
isInterface(): boolean;
147
148
/** Check if this is an object type */
149
isObject(): boolean;
150
151
/** Check if this is a type parameter */
152
isTypeParameter(): boolean;
153
154
/** Check if this is a union type */
155
isUnion(): boolean;
156
157
/** Check if this is an intersection type */
158
isIntersection(): boolean;
159
160
/** Check if this is an anonymous type */
161
isAnonymous(): boolean;
162
163
/** Check if this is null */
164
isNull(): boolean;
165
166
/** Check if this is undefined */
167
isUndefined(): boolean;
168
169
/** Check if this is never */
170
isNever(): boolean;
171
172
/** Check if this is unknown */
173
isUnknown(): boolean;
174
175
/** Check if this is any */
176
isAny(): boolean;
177
178
/** Get literal value for literal types */
179
getLiteralValue(): string | number | boolean | undefined;
180
181
/** Get properties of this type */
182
getProperties(): Symbol[];
183
184
/** Get property by name */
185
getProperty(name: string): Symbol | undefined;
186
187
/** Get non-nullable type (removes null and undefined) */
188
getNonNullableType(): Type;
189
}
190
```
191
192
### Symbol Class
193
194
Represents a TypeScript symbol with name, declarations, and type information.
195
196
```typescript { .api }
197
class Symbol {
198
/** Get the symbol name */
199
getName(): string;
200
201
/** Get the escaped name */
202
getEscapedName(): string;
203
204
/** Get all declarations of this symbol */
205
getDeclarations(): Node[];
206
207
/** Get first declaration */
208
getFirstDeclaration(): Node | undefined;
209
210
/** Get value declaration (for symbols that have values) */
211
getValueDeclaration(): Node | undefined;
212
213
/** Get type declaration (for type symbols) */
214
getTypeDeclaration(): Node | undefined;
215
216
/** Get the symbol flags */
217
getFlags(): SymbolFlags;
218
219
/** Get exports if this is a module or namespace */
220
getExports(): Symbol[];
221
222
/** Get global exports */
223
getGlobalExports(): Symbol[];
224
225
/** Get members if this is a class or interface */
226
getMembers(): Symbol[];
227
228
/** Get the type of this symbol */
229
getTypeAtLocation(location: Node): Type;
230
231
/** Get documentation comment */
232
getDocumentationComment(): SymbolDisplayPart[];
233
234
/** Get JSDoc tags */
235
getJsDocTags(): JSDocTagInfo[];
236
237
/** Check if symbol has specific flag */
238
hasFlag(flag: SymbolFlags): boolean;
239
240
/** Check if symbol is optional */
241
isOptional(): boolean;
242
}
243
```
244
245
### Signature Class
246
247
Represents a function or method signature with parameter and return type information.
248
249
```typescript { .api }
250
class Signature {
251
/** Get parameters of this signature */
252
getParameters(): Symbol[];
253
254
/** Get return type */
255
getReturnType(): Type;
256
257
/** Get type parameters */
258
getTypeParameters(): TypeParameter[];
259
260
/** Get the declaration associated with this signature */
261
getDeclaration(): SignatureDeclaration | undefined;
262
263
/** Get documentation comment */
264
getDocumentationComment(): SymbolDisplayPart[];
265
266
/** Get JSDoc tags */
267
getJsDocTags(): JSDocTagInfo[];
268
269
/** Get signature string representation */
270
getText(): string;
271
}
272
273
class TypeParameter extends Type {
274
/** Get the constraint of this type parameter */
275
getConstraint(): Type | undefined;
276
277
/** Get the default type of this type parameter */
278
getDefault(): Type | undefined;
279
}
280
```
281
282
### Diagnostic Information
283
284
TypeScript diagnostic information for errors, warnings, and suggestions.
285
286
```typescript { .api }
287
class Diagnostic {
288
/** Get the diagnostic message text */
289
getMessageText(): string;
290
291
/** Get the source file where this diagnostic occurred */
292
getSourceFile(): SourceFile | undefined;
293
294
/** Get the start position */
295
getStart(): number | undefined;
296
297
/** Get the length */
298
getLength(): number | undefined;
299
300
/** Get the end position */
301
getEnd(): number | undefined;
302
303
/** Get diagnostic category */
304
getCategory(): DiagnosticCategory;
305
306
/** Get diagnostic code */
307
getCode(): number;
308
309
/** Get the line number (1-indexed) */
310
getLineNumber(): number | undefined;
311
}
312
313
interface SymbolDisplayPart {
314
text: string;
315
kind: string;
316
}
317
318
interface JSDocTagInfo {
319
name: string;
320
text?: SymbolDisplayPart[];
321
}
322
```
323
324
### Language Service
325
326
TypeScript language service providing IDE-like functionality.
327
328
```typescript { .api }
329
class LanguageService {
330
/** Get completions at a position */
331
getCompletionsAtPosition(fileName: string, position: number): CompletionInfo | undefined;
332
333
/** Get quick info at a position */
334
getQuickInfoAtPosition(fileName: string, position: number): QuickInfo | undefined;
335
336
/** Get definition at a position */
337
getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[];
338
339
/** Get type definition at a position */
340
getTypeDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[];
341
342
/** Get references at a position */
343
getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[];
344
345
/** Get semantic diagnostics */
346
getSemanticDiagnostics(fileName: string): Diagnostic[];
347
348
/** Get syntactic diagnostics */
349
getSyntacticDiagnostics(fileName: string): Diagnostic[];
350
351
/** Get suggestion diagnostics */
352
getSuggestionDiagnostics(fileName: string): DiagnosticWithLocation[];
353
354
/** Find all references */
355
findReferences(fileName: string, position: number): ReferencedSymbol[];
356
357
/** Get rename info */
358
getRenameInfo(fileName: string, position: number): RenameInfo;
359
360
/** Find rename locations */
361
findRenameLocations(fileName: string, position: number, findInStrings?: boolean, findInComments?: boolean): RenameLocation[];
362
}
363
364
interface CompletionInfo {
365
entries: CompletionEntry[];
366
isGlobalCompletion: boolean;
367
isMemberCompletion: boolean;
368
isNewIdentifierLocation: boolean;
369
}
370
371
interface CompletionEntry {
372
name: string;
373
kind: string;
374
kindModifiers?: string;
375
sortText: string;
376
insertText?: string;
377
replacementSpan?: TextSpan;
378
}
379
380
interface QuickInfo {
381
kind: string;
382
kindModifiers: string;
383
textSpan: TextSpan;
384
displayParts?: SymbolDisplayPart[];
385
documentation?: SymbolDisplayPart[];
386
tags?: JSDocTagInfo[];
387
}
388
389
interface DefinitionInfo {
390
fileName: string;
391
textSpan: TextSpan;
392
kind: string;
393
name: string;
394
containerKind: string;
395
containerName: string;
396
}
397
398
interface TextSpan {
399
start: number;
400
length: number;
401
}
402
```
403
404
**Usage Examples:**
405
406
```typescript
407
import { Project, SyntaxKind } from "ts-morph";
408
409
const project = new Project({
410
tsConfigFilePath: "tsconfig.json",
411
});
412
413
const sourceFile = project.createSourceFile("analysis.ts", `
414
interface User {
415
id: number;
416
name: string;
417
email?: string;
418
}
419
420
class UserService {
421
private users: User[] = [];
422
423
async getUser(id: number): Promise<User | undefined> {
424
return this.users.find(user => user.id === id);
425
}
426
}
427
428
const service = new UserService();
429
const user = service.getUser(1);
430
`);
431
432
const typeChecker = project.getTypeChecker();
433
434
// Analyze types
435
const userInterface = sourceFile.getInterfaceOrThrow("User");
436
const userType = typeChecker.getTypeAtLocation(userInterface);
437
438
console.log("User type text:", userType.getText());
439
console.log("Is User an object type:", userType.isObject());
440
441
// Get properties of User interface
442
const properties = userType.getProperties();
443
properties.forEach(prop => {
444
const propType = typeChecker.getTypeOfSymbolAtLocation(prop, userInterface);
445
console.log(\`Property \${prop.getName()}: \${propType.getText()}\`);
446
console.log(\`Is optional: \${prop.isOptional()}\`);
447
});
448
449
// Analyze method return types
450
const userServiceClass = sourceFile.getClassOrThrow("UserService");
451
const getUserMethod = userServiceClass.getMethodOrThrow("getUser");
452
const signature = typeChecker.getSignatureFromDeclaration(getUserMethod);
453
454
if (signature) {
455
const returnType = signature.getReturnType();
456
console.log("getUser return type:", returnType.getText());
457
console.log("Is Promise:", returnType.getText().startsWith("Promise"));
458
459
// Get the actual type inside Promise
460
const typeArgs = returnType.getTypeArguments();
461
if (typeArgs.length > 0) {
462
console.log("Promise type argument:", typeArgs[0].getText());
463
}
464
}
465
466
// Analyze variable types
467
const serviceVariable = sourceFile.getVariableDeclarationOrThrow("service");
468
const serviceType = typeChecker.getTypeAtLocation(serviceVariable);
469
console.log("Service variable type:", serviceType.getText());
470
471
// Find all number literal types
472
const numberLiterals = sourceFile.getDescendantsOfKind(SyntaxKind.NumericLiteral);
473
numberLiterals.forEach(literal => {
474
const type = typeChecker.getTypeAtLocation(literal);
475
console.log(\`Number literal \${literal.getText()} has type: \${type.getText()}\`);
476
console.log("Is number literal type:", type.isNumberLiteral());
477
if (type.isNumberLiteral()) {
478
console.log("Literal value:", type.getLiteralValue());
479
}
480
});
481
482
// Check type assignability
483
const numberType = typeChecker.getTypeAtLocation(
484
sourceFile.getFirstDescendantByKindOrThrow(SyntaxKind.NumericLiteral)
485
);
486
const stringType = typeChecker.getTypeAtLocation(
487
sourceFile.addVariableStatement({
488
declarationKind: "const",
489
declarations: [{ name: "temp", initializer: "'hello'" }]
490
}).getDeclarations()[0]
491
);
492
493
console.log("Can assign string to number:",
494
typeChecker.isTypeAssignableTo(stringType, numberType));
495
```
496
497
**Advanced Type Analysis:**
498
499
```typescript
500
import { Project } from "ts-morph";
501
502
const project = new Project();
503
const sourceFile = project.createSourceFile("advanced.ts", `
504
type EventHandler<T> = (event: T) => void;
505
506
interface ClickEvent {
507
type: 'click';
508
x: number;
509
y: number;
510
}
511
512
interface KeyEvent {
513
type: 'key';
514
key: string;
515
code: number;
516
}
517
518
type AllEvents = ClickEvent | KeyEvent;
519
520
class EventEmitter {
521
private handlers: Map<string, EventHandler<any>[]> = new Map();
522
523
on<T extends AllEvents>(type: T['type'], handler: EventHandler<T>): void {
524
// Implementation
525
}
526
}
527
`);
528
529
const typeChecker = project.getTypeChecker();
530
531
// Analyze generic types
532
const eventHandlerType = sourceFile.getTypeAliasOrThrow("EventHandler");
533
const handlerType = typeChecker.getTypeAtLocation(eventHandlerType);
534
535
console.log("EventHandler type:", handlerType.getText());
536
537
// Analyze union types
538
const allEventsType = sourceFile.getTypeAliasOrThrow("AllEvents");
539
const unionType = typeChecker.getTypeAtLocation(allEventsType);
540
541
console.log("AllEvents is union:", unionType.isUnion());
542
if (unionType.isUnion()) {
543
const unionTypes = unionType.getUnionTypes();
544
unionTypes.forEach((type, index) => {
545
console.log(\`Union member \${index}: \${type.getText()}\`);
546
547
// Analyze each union member's properties
548
const properties = type.getProperties();
549
properties.forEach(prop => {
550
const propType = typeChecker.getTypeOfSymbolAtLocation(prop, allEventsType);
551
console.log(\` Property \${prop.getName()}: \${propType.getText()}\`);
552
});
553
});
554
}
555
556
// Analyze generic method constraints
557
const eventEmitterClass = sourceFile.getClassOrThrow("EventEmitter");
558
const onMethod = eventEmitterClass.getMethodOrThrow("on");
559
const onSignature = typeChecker.getSignatureFromDeclaration(onMethod);
560
561
if (onSignature) {
562
const typeParams = onSignature.getTypeParameters();
563
typeParams.forEach(typeParam => {
564
console.log("Type parameter:", typeParam.getText());
565
const constraint = typeParam.getConstraint();
566
if (constraint) {
567
console.log("Constraint:", constraint.getText());
568
}
569
});
570
}
571
```