0
# Utilities and Helpers
1
2
Essential utility functions for working with TypeScript AST nodes, including type guards, text operations, and traversal helpers.
3
4
## Capabilities
5
6
### Type Guards
7
8
Functions that determine the type of AST nodes at runtime.
9
10
```typescript { .api }
11
/**
12
* Check if node is an identifier
13
* @param node - Node to test
14
* @returns True if node is an identifier
15
*/
16
function isIdentifier(node: Node): node is Identifier;
17
18
/**
19
* Check if node is a string literal
20
* @param node - Node to test
21
* @returns True if node is a string literal
22
*/
23
function isStringLiteral(node: Node): node is StringLiteral;
24
25
/**
26
* Check if node is a numeric literal
27
* @param node - Node to test
28
* @returns True if node is a numeric literal
29
*/
30
function isNumericLiteral(node: Node): node is NumericLiteral;
31
32
/**
33
* Check if node is a function declaration
34
* @param node - Node to test
35
* @returns True if node is a function declaration
36
*/
37
function isFunctionDeclaration(node: Node): node is FunctionDeclaration;
38
39
/**
40
* Check if node is a class declaration
41
* @param node - Node to test
42
* @returns True if node is a class declaration
43
*/
44
function isClassDeclaration(node: Node): node is ClassDeclaration;
45
46
/**
47
* Check if node is an interface declaration
48
* @param node - Node to test
49
* @returns True if node is an interface declaration
50
*/
51
function isInterfaceDeclaration(node: Node): node is InterfaceDeclaration;
52
53
/**
54
* Check if node is a variable declaration
55
* @param node - Node to test
56
* @returns True if node is a variable declaration
57
*/
58
function isVariableDeclaration(node: Node): node is VariableDeclaration;
59
60
/**
61
* Check if node is a method declaration
62
* @param node - Node to test
63
* @returns True if node is a method declaration
64
*/
65
function isMethodDeclaration(node: Node): node is MethodDeclaration;
66
67
/**
68
* Check if node is a property declaration
69
* @param node - Node to test
70
* @returns True if node is a property declaration
71
*/
72
function isPropertyDeclaration(node: Node): node is PropertyDeclaration;
73
74
/**
75
* Check if node is a parameter declaration
76
* @param node - Node to test
77
* @returns True if node is a parameter declaration
78
*/
79
function isParameterDeclaration(node: Node): node is ParameterDeclaration;
80
```
81
82
**Usage Examples:**
83
84
```typescript
85
import * as ts from "typescript";
86
87
const sourceFile = ts.createSourceFile(
88
"example.ts",
89
`
90
class User {
91
name: string;
92
constructor(name: string) {
93
this.name = name;
94
}
95
greet(): string {
96
return "Hello!";
97
}
98
}
99
`,
100
ts.ScriptTarget.Latest
101
);
102
103
function analyzeNode(node: ts.Node) {
104
if (ts.isClassDeclaration(node)) {
105
console.log(`Found class: ${node.name?.text}`);
106
107
for (const member of node.members) {
108
if (ts.isPropertyDeclaration(member)) {
109
console.log(` Property: ${member.name?.getText()}`);
110
} else if (ts.isMethodDeclaration(member)) {
111
console.log(` Method: ${member.name?.getText()}`);
112
} else if (ts.isConstructorDeclaration(member)) {
113
console.log(` Constructor with ${member.parameters.length} parameters`);
114
}
115
}
116
}
117
118
ts.forEachChild(node, analyzeNode);
119
}
120
121
analyzeNode(sourceFile);
122
```
123
124
### Expression Type Guards
125
126
Type guards for various expression types.
127
128
```typescript { .api }
129
/**
130
* Check if node is an expression
131
* @param node - Node to test
132
* @returns True if node is an expression
133
*/
134
function isExpression(node: Node): node is Expression;
135
136
/**
137
* Check if node is a call expression
138
* @param node - Node to test
139
* @returns True if node is a call expression
140
*/
141
function isCallExpression(node: Node): node is CallExpression;
142
143
/**
144
* Check if node is a property access expression
145
* @param node - Node to test
146
* @returns True if node is a property access expression
147
*/
148
function isPropertyAccessExpression(node: Node): node is PropertyAccessExpression;
149
150
/**
151
* Check if node is an element access expression
152
* @param node - Node to test
153
* @returns True if node is an element access expression
154
*/
155
function isElementAccessExpression(node: Node): node is ElementAccessExpression;
156
157
/**
158
* Check if node is a binary expression
159
* @param node - Node to test
160
* @returns True if node is a binary expression
161
*/
162
function isBinaryExpression(node: Node): node is BinaryExpression;
163
164
/**
165
* Check if node is a conditional expression
166
* @param node - Node to test
167
* @returns True if node is a conditional expression
168
*/
169
function isConditionalExpression(node: Node): node is ConditionalExpression;
170
171
/**
172
* Check if node is an arrow function
173
* @param node - Node to test
174
* @returns True if node is an arrow function
175
*/
176
function isArrowFunction(node: Node): node is ArrowFunction;
177
178
/**
179
* Check if node is a template expression
180
* @param node - Node to test
181
* @returns True if node is a template expression
182
*/
183
function isTemplateExpression(node: Node): node is TemplateExpression;
184
185
/**
186
* Check if node is an object literal expression
187
* @param node - Node to test
188
* @returns True if node is an object literal expression
189
*/
190
function isObjectLiteralExpression(node: Node): node is ObjectLiteralExpression;
191
192
/**
193
* Check if node is an array literal expression
194
* @param node - Node to test
195
* @returns True if node is an array literal expression
196
*/
197
function isArrayLiteralExpression(node: Node): node is ArrayLiteralExpression;
198
```
199
200
### Statement Type Guards
201
202
Type guards for various statement types.
203
204
```typescript { .api }
205
/**
206
* Check if node is a statement
207
* @param node - Node to test
208
* @returns True if node is a statement
209
*/
210
function isStatement(node: Node): node is Statement;
211
212
/**
213
* Check if node is a block statement
214
* @param node - Node to test
215
* @returns True if node is a block statement
216
*/
217
function isBlock(node: Node): node is Block;
218
219
/**
220
* Check if node is an if statement
221
* @param node - Node to test
222
* @returns True if node is an if statement
223
*/
224
function isIfStatement(node: Node): node is IfStatement;
225
226
/**
227
* Check if node is a for statement
228
* @param node - Node to test
229
* @returns True if node is a for statement
230
*/
231
function isForStatement(node: Node): node is ForStatement;
232
233
/**
234
* Check if node is a while statement
235
* @param node - Node to test
236
* @returns True if node is a while statement
237
*/
238
function isWhileStatement(node: Node): node is WhileStatement;
239
240
/**
241
* Check if node is a return statement
242
* @param node - Node to test
243
* @returns True if node is a return statement
244
*/
245
function isReturnStatement(node: Node): node is ReturnStatement;
246
247
/**
248
* Check if node is a try statement
249
* @param node - Node to test
250
* @returns True if node is a try statement
251
*/
252
function isTryStatement(node: Node): node is TryStatement;
253
254
/**
255
* Check if node is a switch statement
256
* @param node - Node to test
257
* @returns True if node is a switch statement
258
*/
259
function isSwitchStatement(node: Node): node is SwitchStatement;
260
261
/**
262
* Check if node is an expression statement
263
* @param node - Node to test
264
* @returns True if node is an expression statement
265
*/
266
function isExpressionStatement(node: Node): node is ExpressionStatement;
267
268
/**
269
* Check if node is a variable statement
270
* @param node - Node to test
271
* @returns True if node is a variable statement
272
*/
273
function isVariableStatement(node: Node): node is VariableStatement;
274
```
275
276
### Type Node Guards
277
278
Type guards for TypeScript type annotations.
279
280
```typescript { .api }
281
/**
282
* Check if node is a type node
283
* @param node - Node to test
284
* @returns True if node is a type node
285
*/
286
function isTypeNode(node: Node): node is TypeNode;
287
288
/**
289
* Check if node is a type reference node
290
* @param node - Node to test
291
* @returns True if node is a type reference node
292
*/
293
function isTypeReferenceNode(node: Node): node is TypeReferenceNode;
294
295
/**
296
* Check if node is a union type node
297
* @param node - Node to test
298
* @returns True if node is a union type node
299
*/
300
function isUnionTypeNode(node: Node): node is UnionTypeNode;
301
302
/**
303
* Check if node is an intersection type node
304
* @param node - Node to test
305
* @returns True if node is an intersection type node
306
*/
307
function isIntersectionTypeNode(node: Node): node is IntersectionTypeNode;
308
309
/**
310
* Check if node is an array type node
311
* @param node - Node to test
312
* @returns True if node is an array type node
313
*/
314
function isArrayTypeNode(node: Node): node is ArrayTypeNode;
315
316
/**
317
* Check if node is a tuple type node
318
* @param node - Node to test
319
* @returns True if node is a tuple type node
320
*/
321
function isTupleTypeNode(node: Node): node is TupleTypeNode;
322
323
/**
324
* Check if node is a function type node
325
* @param node - Node to test
326
* @returns True if node is a function type node
327
*/
328
function isFunctionTypeNode(node: Node): node is FunctionTypeNode;
329
330
/**
331
* Check if node is a mapped type node
332
* @param node - Node to test
333
* @returns True if node is a mapped type node
334
*/
335
function isMappedTypeNode(node: Node): node is MappedTypeNode;
336
337
/**
338
* Check if node is a conditional type node
339
* @param node - Node to test
340
* @returns True if node is a conditional type node
341
*/
342
function isConditionalTypeNode(node: Node): node is ConditionalTypeNode;
343
344
/**
345
* Check if node is a literal type node
346
* @param node - Node to test
347
* @returns True if node is a literal type node
348
*/
349
function isLiteralTypeNode(node: Node): node is LiteralTypeNode;
350
```
351
352
### Node Navigation
353
354
Functions for traversing and finding AST nodes.
355
356
```typescript { .api }
357
/**
358
* Get the original node before transformations
359
* @param node - Node to get original for
360
* @param nodeTest - Optional test function to validate result
361
* @returns Original node
362
*/
363
function getOriginalNode(node: Node): Node;
364
function getOriginalNode<T extends Node>(node: Node, nodeTest: (node: Node) => node is T): T;
365
function getOriginalNode(node: Node | undefined): Node | undefined;
366
function getOriginalNode<T extends Node>(node: Node | undefined, nodeTest: (node: Node | undefined) => node is T): T | undefined;
367
368
/**
369
* Find ancestor node matching predicate
370
* @param node - Starting node
371
* @param callback - Predicate function
372
* @returns Found ancestor or undefined
373
*/
374
function findAncestor<T extends Node>(node: Node | undefined, callback: (element: Node) => element is T): T | undefined;
375
function findAncestor(node: Node | undefined, callback: (element: Node) => boolean): Node | undefined;
376
377
/**
378
* Check if node is from original parse tree
379
* @param node - Node to check
380
* @returns True if from parse tree
381
*/
382
function isParseTreeNode(node: Node): boolean;
383
384
/**
385
* Get original parse tree node
386
* @param node - Node to get parse tree node for
387
* @param nodeTest - Optional test function
388
* @returns Parse tree node
389
*/
390
function getParseTreeNode(node: Node | undefined): Node | undefined;
391
function getParseTreeNode<T extends Node>(node: T | undefined, nodeTest?: (node: Node) => node is T): T | undefined;
392
393
/**
394
* Get all leading trivia for a node
395
* @param node - Node to get trivia for
396
* @param sourceFile - Source file containing the node
397
* @param includeJSDoc - Whether to include JSDoc comments
398
* @returns Array of trivia ranges
399
*/
400
function getLeadingCommentRanges(text: string, pos: number): CommentRange[] | undefined;
401
402
/**
403
* Get all trailing trivia for a node
404
* @param text - Source text
405
* @param pos - Position to start from
406
* @returns Array of trivia ranges
407
*/
408
function getTrailingCommentRanges(text: string, pos: number): CommentRange[] | undefined;
409
```
410
411
**Usage Examples:**
412
413
```typescript
414
import * as ts from "typescript";
415
416
// Find all function declarations in a class
417
function findFunctionsInClass(classNode: ts.ClassDeclaration): ts.FunctionLikeDeclaration[] {
418
const functions: ts.FunctionLikeDeclaration[] = [];
419
420
function visit(node: ts.Node) {
421
if (ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node) || ts.isArrowFunction(node)) {
422
functions.push(node);
423
}
424
ts.forEachChild(node, visit);
425
}
426
427
visit(classNode);
428
return functions;
429
}
430
431
// Find the containing class for a method
432
function findContainingClass(node: ts.Node): ts.ClassDeclaration | undefined {
433
return ts.findAncestor(node, ts.isClassDeclaration);
434
}
435
```
436
437
### Text and Position Utilities
438
439
Functions for working with text positions and spans.
440
441
```typescript { .api }
442
/**
443
* Get the end position of a text span
444
* @param span - Text span
445
* @returns End position
446
*/
447
function textSpanEnd(span: TextSpan): number;
448
449
/**
450
* Check if a text span contains a position
451
* @param span - Text span to check
452
* @param position - Position to test
453
* @returns True if span contains position
454
*/
455
function textSpanContainsPosition(span: TextSpan, position: number): boolean;
456
457
/**
458
* Check if a text span contains another text span
459
* @param span - Container span
460
* @param other - Contained span
461
* @returns True if span contains other
462
*/
463
function textSpanContainsTextSpan(span: TextSpan, other: TextSpan): boolean;
464
465
/**
466
* Check if two text spans overlap
467
* @param span1 - First span
468
* @param span2 - Second span
469
* @returns True if spans overlap
470
*/
471
function textSpanOverlapsWith(span1: TextSpan, span2: TextSpan): boolean;
472
473
/**
474
* Get intersection of two text spans
475
* @param span1 - First span
476
* @param span2 - Second span
477
* @returns Intersection span or undefined
478
*/
479
function textSpanIntersection(span1: TextSpan, span2: TextSpan): TextSpan | undefined;
480
481
/**
482
* Create a text span
483
* @param start - Start position
484
* @param length - Length of span
485
* @returns Text span object
486
*/
487
function createTextSpan(start: number, length: number): TextSpan;
488
489
/**
490
* Check if a text span is empty (has zero length)
491
* @param span - Text span to check
492
* @returns True if span is empty
493
*/
494
function textSpanIsEmpty(span: TextSpan): boolean;
495
496
/**
497
* Create a text change range
498
* @param span - Text span being changed
499
* @param newLength - New length after change
500
* @returns Text change range object
501
*/
502
function createTextChangeRange(span: TextSpan, newLength: number): TextChangeRange;
503
504
/**
505
* Collapse multiple text change ranges across versions
506
* @param changes - Array of text change ranges
507
* @returns Collapsed text change range
508
*/
509
function collapseTextChangeRangesAcrossMultipleVersions(changes: readonly TextChangeRange[]): TextChangeRange;
510
```
511
512
### Identifier Utilities
513
514
Functions for working with TypeScript identifiers.
515
516
```typescript { .api }
517
/**
518
* Escape leading underscores in identifier for internal use
519
* @param identifier - Identifier text
520
* @returns Escaped identifier
521
*/
522
function escapeLeadingUnderscores(identifier: string): __String;
523
524
/**
525
* Unescape leading underscores for display
526
* @param identifier - Escaped identifier
527
* @returns Unescaped identifier text
528
*/
529
function unescapeLeadingUnderscores(identifier: __String): string;
530
531
/**
532
* Get text content of identifier node
533
* @param identifier - Identifier node
534
* @returns Identifier text
535
*/
536
function idText(identifier: Identifier): string;
537
538
/**
539
* Get display name of symbol
540
* @param symbol - Symbol to get name for
541
* @returns Symbol display name
542
*/
543
function symbolName(symbol: Symbol): string;
544
545
/**
546
* Check if identifier name is reserved word
547
* @param name - Identifier name to check
548
* @param languageVersion - Language version context
549
* @returns True if reserved word
550
*/
551
function isIdentifierANonContextualKeyword(name: string): boolean;
552
553
/**
554
* Check if text is a valid identifier
555
* @param text - Text to validate
556
* @param languageVersion - Language version context
557
* @returns True if valid identifier
558
*/
559
function isValidIdentifier(text: string, languageVersion?: ScriptTarget): boolean;
560
```
561
562
### JSDoc Utilities
563
564
Functions for working with JSDoc comments and annotations.
565
566
```typescript { .api }
567
/**
568
* Get all JSDoc tags for an AST node
569
* @param node - Node to get JSDoc tags for
570
* @returns Array of JSDoc tag nodes
571
*/
572
function getJSDocTags(node: Node): readonly JSDocTag[] | undefined;
573
574
/**
575
* Get JSDoc type annotation for a node
576
* @param node - Node to get JSDoc type for
577
* @returns JSDoc type node
578
*/
579
function getJSDocType(node: Node): TypeNode | undefined;
580
581
/**
582
* Get JSDoc return type annotation
583
* @param node - Node to get return type for
584
* @returns JSDoc return type node
585
*/
586
function getJSDocReturnType(node: Node): TypeNode | undefined;
587
588
/**
589
* Extract text content from JSDoc comment
590
* @param comment - JSDoc comment node
591
* @returns Comment text
592
*/
593
function getTextOfJSDocComment(comment: JSDocComment | undefined): string | undefined;
594
595
/**
596
* Get JSDoc parameter tags for a function
597
* @param node - Function node
598
* @returns Array of JSDoc parameter tags
599
*/
600
function getJSDocParameterTags(node: FunctionLikeDeclaration): readonly JSDocParameterTag[];
601
602
/**
603
* Get JSDoc deprecated tag if present
604
* @param node - Node to check
605
* @returns JSDoc deprecated tag
606
*/
607
function getJSDocDeprecatedTag(node: Node): JSDocDeprecatedTag | undefined;
608
609
/**
610
* Get all JSDoc comments for a node including parents
611
* @param node - Node to get comments for
612
* @param sourceFile - Source file containing node
613
* @returns Array of JSDoc comment nodes
614
*/
615
function getJSDocCommentsAndTags(node: Node, checkParentVariableStatement?: boolean): readonly (JSDoc | JSDocTag)[];
616
```
617
618
**Usage Examples:**
619
620
```typescript
621
import * as ts from "typescript";
622
623
// Extract JSDoc information from functions
624
function analyzeJSDoc(node: ts.FunctionDeclaration) {
625
const jsdocTags = ts.getJSDocTags(node);
626
if (jsdocTags) {
627
for (const tag of jsdocTags) {
628
if (ts.isJSDocParameterTag(tag)) {
629
console.log(`@param ${tag.name?.getText()}: ${tag.comment}`);
630
} else if (ts.isJSDocReturnTag(tag)) {
631
console.log(`@returns: ${tag.comment}`);
632
}
633
}
634
}
635
636
const deprecatedTag = ts.getJSDocDeprecatedTag(node);
637
if (deprecatedTag) {
638
console.log(`Function is deprecated: ${deprecatedTag.comment}`);
639
}
640
}
641
```
642
643
### Syntax Kind Utilities
644
645
Functions for working with syntax kinds and tokens.
646
647
```typescript { .api }
648
/**
649
* Check if syntax kind is a token
650
* @param kind - Syntax kind to test
651
* @returns True if kind is a token
652
*/
653
function isToken(kind: SyntaxKind): boolean;
654
655
/**
656
* Check if syntax kind is a keyword
657
* @param kind - Syntax kind to test
658
* @returns True if kind is a keyword
659
*/
660
function isKeyword(kind: SyntaxKind): boolean;
661
662
/**
663
* Check if syntax kind is a modifier
664
* @param kind - Syntax kind to test
665
* @returns True if kind is a modifier
666
*/
667
function isModifierKind(kind: SyntaxKind): boolean;
668
669
/**
670
* Check if syntax kind is a literal
671
* @param kind - Syntax kind to test
672
* @returns True if kind is a literal
673
*/
674
function isLiteralKind(kind: SyntaxKind): boolean;
675
676
/**
677
* Check if syntax kind is a punctuation token
678
* @param kind - Syntax kind to test
679
* @returns True if kind is punctuation
680
*/
681
function isPunctuation(kind: SyntaxKind): boolean;
682
683
/**
684
* Get token text for a syntax kind
685
* @param kind - Syntax kind
686
* @returns Token text or undefined
687
*/
688
function tokenToString(kind: SyntaxKind): string | undefined;
689
690
/**
691
* Get syntax kind from token text
692
* @param text - Token text
693
* @returns Syntax kind or undefined
694
*/
695
function stringToToken(text: string): SyntaxKind | undefined;
696
```
697
698
### Binding Pattern Utilities
699
700
Functions for working with destructuring patterns.
701
702
```typescript { .api }
703
/**
704
* Check if node is a binding pattern
705
* @param node - Node to test
706
* @returns True if node is binding pattern
707
*/
708
function isBindingPattern(node: Node | undefined): node is BindingPattern;
709
710
/**
711
* Check if node is an object binding pattern
712
* @param node - Node to test
713
* @returns True if node is object binding pattern
714
*/
715
function isObjectBindingPattern(node: Node): node is ObjectBindingPattern;
716
717
/**
718
* Check if node is an array binding pattern
719
* @param node - Node to test
720
* @returns True if node is array binding pattern
721
*/
722
function isArrayBindingPattern(node: Node): node is ArrayBindingPattern;
723
724
/**
725
* Check if node is a binding element
726
* @param node - Node to test
727
* @returns True if node is binding element
728
*/
729
function isBindingElement(node: Node): node is BindingElement;
730
731
/**
732
* Check if binding element is a rest element
733
* @param node - Binding element to test
734
* @returns True if rest element
735
*/
736
function isRestElement(node: Node): node is RestElement;
737
738
/**
739
* Get name from binding pattern element
740
* @param element - Binding element
741
* @returns Element name
742
*/
743
function getNameOfBindingElement(element: BindingElement): string | undefined;
744
```
745
746
## Types
747
748
### Utility Types
749
750
```typescript { .api }
751
type __String = string & { __escapedIdentifier: void };
752
753
interface TextSpan {
754
start: number;
755
length: number;
756
}
757
758
interface TextChangeRange {
759
span: TextSpan;
760
newLength: number;
761
}
762
763
interface CommentRange extends TextRange {
764
hasTrailingNewLine?: boolean;
765
kind: CommentKind;
766
}
767
768
enum CommentKind {
769
SingleLine = 0,
770
MultiLine = 1
771
}
772
773
interface JSDocComment {
774
kind: SyntaxKind.JSDocComment;
775
comment?: string | NodeArray<JSDocText | JSDocLink>;
776
tags?: NodeArray<JSDocTag>;
777
}
778
779
interface JSDocTag extends Node {
780
parent: JSDoc | JSDocTypeLiteral;
781
tagName: Identifier;
782
comment?: string | NodeArray<JSDocText | JSDocLink>;
783
}
784
785
interface JSDocParameterTag extends JSDocTag {
786
kind: SyntaxKind.JSDocParameterTag;
787
name: EntityName;
788
typeExpression?: JSDocTypeExpression;
789
isNameFirst: boolean;
790
isBracketed: boolean;
791
}
792
```
793
794
### Type Guard Result Types
795
796
```typescript { .api }
797
// All type guard functions return type predicates
798
// Example signatures:
799
function isIdentifier(node: Node): node is Identifier;
800
function isFunctionDeclaration(node: Node): node is FunctionDeclaration;
801
function isStringLiteral(node: Node): node is StringLiteral;
802
803
// These enable TypeScript to narrow types automatically
804
const node: ts.Node = getNode();
805
if (ts.isIdentifier(node)) {
806
// node is now typed as ts.Identifier
807
console.log(node.text); // TypeScript knows 'text' property exists
808
}
809
810
if (ts.isFunctionDeclaration(node)) {
811
// node is now typed as ts.FunctionDeclaration
812
console.log(node.name?.text); // TypeScript knows about function properties
813
}
814
```