or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

ast-utils.mdeslint-utils.mdindex.mdjson-schema.mdscope-analysis.mdts-eslint.mdts-estree.md

ast-utils.mddocs/

0

# AST Utilities

1

2

Tools for manipulating and analyzing TypeScript Abstract Syntax Trees, including type guards, predicates, helper functions, and pattern matching utilities.

3

4

## Capabilities

5

6

### Node Type Guards

7

8

Type guards for checking AST node types with full TypeScript type safety.

9

10

```typescript { .api }

11

/**

12

* Creates a type guard function for a specific AST node type

13

* @param nodeType - The AST node type to check for

14

* @returns Type guard function that narrows the node type

15

*/

16

function isNodeOfType<NodeType extends TSESTree.AST_NODE_TYPES>(

17

nodeType: NodeType

18

): (node: TSESTree.Node | null | undefined) => node is Extract<TSESTree.Node, { type: NodeType }>;

19

20

/**

21

* Creates a type guard function for multiple AST node types

22

* @param nodeTypes - Array of AST node types to check for

23

* @returns Type guard function that narrows to one of the specified types

24

*/

25

function isNodeOfTypes<NodeTypes extends readonly TSESTree.AST_NODE_TYPES[]>(

26

nodeTypes: NodeTypes

27

): (node: TSESTree.Node | null | undefined) => node is Extract<TSESTree.Node, { type: NodeTypes[number] }>;

28

29

/**

30

* Creates a conditional type guard with additional constraints

31

* @param nodeType - The AST node type to check for

32

* @param conditions - Additional property conditions to match

33

* @returns Type guard function with type and condition checking

34

*/

35

function isNodeOfTypeWithConditions<

36

NodeType extends TSESTree.AST_NODE_TYPES,

37

Conditions extends Partial<Extract<TSESTree.Node, { type: NodeType }>>

38

>(

39

nodeType: NodeType,

40

conditions: Conditions

41

): (node: TSESTree.Node | null | undefined) => node is Extract<TSESTree.Node, { type: NodeType }> & Conditions;

42

43

/**

44

* Creates a conditional type guard for tokens

45

* @param tokenType - Token type to check for

46

* @param conditions - Additional token conditions

47

* @returns Type guard function for tokens

48

*/

49

function isTokenOfTypeWithConditions<

50

TokenType extends TSESTree.AST_TOKEN_TYPES,

51

Conditions extends Partial<Extract<TSESTree.Token, { type: TokenType }>>

52

>(

53

tokenType: TokenType,

54

conditions: Conditions

55

): (token: TSESTree.Token | null | undefined) => token is Extract<TSESTree.Token, { type: TokenType }> & Conditions;

56

57

/**

58

* Creates a negated conditional type guard for tokens

59

* @param tokenType - Token type to exclude

60

* @param conditions - Additional token conditions to exclude

61

* @returns Negated type guard function

62

*/

63

function isNotTokenOfTypeWithConditions<

64

TokenType extends TSESTree.AST_TOKEN_TYPES,

65

Conditions extends Partial<Extract<TSESTree.Token, { type: TokenType }>>

66

>(

67

tokenType: TokenType,

68

conditions: Conditions

69

): (token: TSESTree.Token | null | undefined) => token is Exclude<TSESTree.Token, Extract<TSESTree.Token, { type: TokenType }> & Conditions>;

70

```

71

72

### Node Predicates

73

74

Predicate functions for identifying specific types of AST nodes.

75

76

```typescript { .api }

77

/**

78

* Checks if a node is an optional call expression (foo?.())

79

*/

80

function isOptionalCallExpression(node: TSESTree.Node | null | undefined): node is TSESTree.CallExpression & { optional: true };

81

82

/**

83

* Checks if a node is a logical OR operator (||)

84

*/

85

function isLogicalOrOperator(node: TSESTree.Node | null | undefined): node is TSESTree.LogicalExpression & { operator: '||' };

86

87

/**

88

* Checks if a node is a type assertion (x as foo or <foo>x)

89

*/

90

function isTypeAssertion(node: TSESTree.Node | null | undefined): node is TSESTree.TSTypeAssertion | TSESTree.TSAsExpression;

91

92

/**

93

* Checks if a node is a variable declarator

94

*/

95

function isVariableDeclarator(node: TSESTree.Node | null | undefined): node is TSESTree.VariableDeclarator;

96

97

/**

98

* Checks if a node is any kind of function (declaration, expression, or arrow)

99

*/

100

function isFunction(node: TSESTree.Node | null | undefined): node is TSESTree.FunctionLike;

101

102

/**

103

* Checks if a node is a function type

104

*/

105

function isFunctionType(node: TSESTree.Node | null | undefined): node is TSESTree.TSFunctionType | TSESTree.TSConstructorType;

106

107

/**

108

* Checks if a node is a function or function type

109

*/

110

function isFunctionOrFunctionType(node: TSESTree.Node | null | undefined): node is TSESTree.FunctionLike | TSESTree.TSFunctionType | TSESTree.TSConstructorType;

111

112

/**

113

* Checks if a node is a TypeScript function type

114

*/

115

function isTSFunctionType(node: TSESTree.Node | null | undefined): node is TSESTree.TSFunctionType;

116

117

/**

118

* Checks if a node is a TypeScript constructor type

119

*/

120

function isTSConstructorType(node: TSESTree.Node | null | undefined): node is TSESTree.TSConstructorType;

121

122

/**

123

* Checks if a node is a class or type element

124

*/

125

function isClassOrTypeElement(node: TSESTree.Node | null | undefined): node is TSESTree.ClassElement | TSESTree.TypeElement;

126

127

/**

128

* Checks if a node is a constructor method

129

*/

130

function isConstructor(node: TSESTree.Node | null | undefined): node is TSESTree.MethodDefinition & { key: TSESTree.Identifier & { name: 'constructor' } };

131

132

/**

133

* Checks if a node is a setter method

134

*/

135

function isSetter(node: TSESTree.Node | null | undefined): node is TSESTree.MethodDefinition & { kind: 'set' } | TSESTree.Property & { kind: 'set' };

136

137

/**

138

* Checks if a node is an identifier

139

*/

140

function isIdentifier(node: TSESTree.Node | null | undefined): node is TSESTree.Identifier;

141

142

/**

143

* Checks if a node is an await expression

144

*/

145

function isAwaitExpression(node: TSESTree.Node | null | undefined): node is TSESTree.AwaitExpression;

146

147

/**

148

* Checks if a node is a loop statement

149

*/

150

function isLoop(node: TSESTree.Node | null | undefined): node is TSESTree.DoWhileStatement | TSESTree.ForStatement | TSESTree.ForInStatement | TSESTree.ForOfStatement | TSESTree.WhileStatement;

151

```

152

153

### Token Predicates

154

155

Predicate functions for identifying specific types of tokens.

156

157

```typescript { .api }

158

/**

159

* Checks if a token is an optional chain punctuator (?.)

160

*/

161

function isOptionalChainPunctuator(token: TSESTree.Token | null | undefined): token is TSESTree.PunctuatorToken & { value: '?.' };

162

163

/**

164

* Checks if a token is NOT an optional chain punctuator

165

*/

166

function isNotOptionalChainPunctuator(token: TSESTree.Token | null | undefined): token is Exclude<TSESTree.Token, TSESTree.PunctuatorToken & { value: '?.' }>;

167

168

/**

169

* Checks if a token is a non-null assertion punctuator (!)

170

*/

171

function isNonNullAssertionPunctuator(token: TSESTree.Token | null | undefined): token is TSESTree.PunctuatorToken & { value: '!' };

172

173

/**

174

* Checks if a token is NOT a non-null assertion punctuator

175

*/

176

function isNotNonNullAssertionPunctuator(token: TSESTree.Token | null | undefined): token is Exclude<TSESTree.Token, TSESTree.PunctuatorToken & { value: '!' }>;

177

178

/**

179

* Checks if a token is an await keyword

180

*/

181

function isAwaitKeyword(token: TSESTree.Token | null | undefined): token is TSESTree.KeywordToken & { value: 'await' };

182

183

/**

184

* Checks if a token is a type keyword

185

*/

186

function isTypeKeyword(token: TSESTree.Token | null | undefined): token is TSESTree.KeywordToken & { value: 'type' };

187

188

/**

189

* Checks if a token is an import keyword

190

*/

191

function isImportKeyword(token: TSESTree.Token | null | undefined): token is TSESTree.KeywordToken & { value: 'import' };

192

193

/**

194

* Checks if a token is an arrow function token (=>)

195

*/

196

function isArrowToken(token: TSESTree.Token | null | undefined): token is TSESTree.PunctuatorToken & { value: '=>' };

197

198

/**

199

* Checks if a token is NOT an arrow function token

200

*/

201

function isNotArrowToken(token: TSESTree.Token | null | undefined): token is Exclude<TSESTree.Token, TSESTree.PunctuatorToken & { value: '=>' }>;

202

203

/**

204

* Checks if a token is a closing brace (})

205

*/

206

function isClosingBraceToken(token: TSESTree.Token | null | undefined): token is TSESTree.PunctuatorToken & { value: '}' };

207

208

/**

209

* Checks if a token is NOT a closing brace

210

*/

211

function isNotClosingBraceToken(token: TSESTree.Token | null | undefined): token is Exclude<TSESTree.Token, TSESTree.PunctuatorToken & { value: '}' }>;

212

213

/**

214

* Checks if a token is a closing bracket (])

215

*/

216

function isClosingBracketToken(token: TSESTree.Token | null | undefined): token is TSESTree.PunctuatorToken & { value: ']' };

217

218

/**

219

* Checks if a token is NOT a closing bracket

220

*/

221

function isNotClosingBracketToken(token: TSESTree.Token | null | undefined): token is Exclude<TSESTree.Token, TSESTree.PunctuatorToken & { value: ']' }>;

222

223

/**

224

* Checks if a token is a closing parenthesis ())

225

*/

226

function isClosingParenToken(token: TSESTree.Token | null | undefined): token is TSESTree.PunctuatorToken & { value: ')' };

227

228

/**

229

* Checks if a token is NOT a closing parenthesis

230

*/

231

function isNotClosingParenToken(token: TSESTree.Token | null | undefined): token is Exclude<TSESTree.Token, TSESTree.PunctuatorToken & { value: ')' }>;

232

233

/**

234

* Checks if a token is a colon (:)

235

*/

236

function isColonToken(token: TSESTree.Token | null | undefined): token is TSESTree.PunctuatorToken & { value: ':' };

237

238

/**

239

* Checks if a token is NOT a colon

240

*/

241

function isNotColonToken(token: TSESTree.Token | null | undefined): token is Exclude<TSESTree.Token, TSESTree.PunctuatorToken & { value: ':' }>;

242

243

/**

244

* Checks if a token is a comma (,)

245

*/

246

function isCommaToken(token: TSESTree.Token | null | undefined): token is TSESTree.PunctuatorToken & { value: ',' };

247

248

/**

249

* Checks if a token is NOT a comma

250

*/

251

function isNotCommaToken(token: TSESTree.Token | null | undefined): token is Exclude<TSESTree.Token, TSESTree.PunctuatorToken & { value: ',' }>;

252

253

/**

254

* Checks if a token is a comment token

255

*/

256

function isCommentToken(token: TSESTree.Token | null | undefined): token is TSESTree.Comment;

257

258

/**

259

* Checks if a token is NOT a comment token

260

*/

261

function isNotCommentToken(token: TSESTree.Token | null | undefined): token is Exclude<TSESTree.Token, TSESTree.Comment>;

262

263

/**

264

* Checks if a token is an opening brace ({)

265

*/

266

function isOpeningBraceToken(token: TSESTree.Token | null | undefined): token is TSESTree.PunctuatorToken & { value: '{' };

267

268

/**

269

* Checks if a token is NOT an opening brace

270

*/

271

function isNotOpeningBraceToken(token: TSESTree.Token | null | undefined): token is Exclude<TSESTree.Token, TSESTree.PunctuatorToken & { value: '{' }>;

272

273

/**

274

* Checks if a token is an opening bracket ([)

275

*/

276

function isOpeningBracketToken(token: TSESTree.Token | null | undefined): token is TSESTree.PunctuatorToken & { value: '[' };

277

278

/**

279

* Checks if a token is NOT an opening bracket

280

*/

281

function isNotOpeningBracketToken(token: TSESTree.Token | null | undefined): token is Exclude<TSESTree.Token, TSESTree.PunctuatorToken & { value: '[' }>;

282

283

/**

284

* Checks if a token is an opening parenthesis (()

285

*/

286

function isOpeningParenToken(token: TSESTree.Token | null | undefined): token is TSESTree.PunctuatorToken & { value: '(' };

287

288

/**

289

* Checks if a token is NOT an opening parenthesis

290

*/

291

function isNotOpeningParenToken(token: TSESTree.Token | null | undefined): token is Exclude<TSESTree.Token, TSESTree.PunctuatorToken & { value: '(' }>;

292

293

/**

294

* Checks if a token is a semicolon (;)

295

*/

296

function isSemicolonToken(token: TSESTree.Token | null | undefined): token is TSESTree.PunctuatorToken & { value: ';' };

297

298

/**

299

* Checks if a token is NOT a semicolon

300

*/

301

function isNotSemicolonToken(token: TSESTree.Token | null | undefined): token is Exclude<TSESTree.Token, TSESTree.PunctuatorToken & { value: ';' }>;

302

```

303

304

### Miscellaneous Utilities

305

306

Helper functions for common AST analysis tasks.

307

308

```typescript { .api }

309

/**

310

* Regular expression for matching line breaks

311

*/

312

const LINEBREAK_MATCHER: RegExp; // /\r\n|[\r\n\u2028\u2029]/

313

314

/**

315

* Determines whether two adjacent AST nodes or tokens are on the same line

316

* @param left - Left node or token

317

* @param right - Right node or token

318

* @returns True if both are on the same line

319

*/

320

function isTokenOnSameLine(

321

left: TSESTree.Node | TSESTree.Token,

322

right: TSESTree.Node | TSESTree.Token

323

): boolean;

324

```

325

326

### ESLint-specific AST Utilities

327

328

Advanced utilities for ESLint rule development.

329

330

```typescript { .api }

331

/**

332

* Gets the function head location for reporting purposes

333

* @param node - Function-like node

334

* @param sourceCode - ESLint source code object

335

* @returns Location object suitable for error reporting

336

*/

337

function getFunctionHeadLocation(

338

node: TSESTree.FunctionLike,

339

sourceCode: TSESLint.SourceCode

340

): TSESTree.SourceLocation;

341

342

/**

343

* Gets the function name with its kind (e.g. "function foo", "method bar")

344

* @param node - Function-like node

345

* @param sourceCode - Optional source code object for getting text

346

* @returns Descriptive function name string

347

*/

348

function getFunctionNameWithKind(

349

node: TSESTree.FunctionLike,

350

sourceCode?: TSESLint.SourceCode

351

): string;

352

353

/**

354

* Gets the property name from property-like nodes

355

* @param node - Property-like AST node

356

* @param initialScope - Optional initial scope for evaluation

357

* @returns Property name string or null if not determinable

358

*/

359

function getPropertyName(

360

node: TSESTree.PropertyLike,

361

initialScope?: TSESLintScope.Scope

362

): string | null;

363

364

/**

365

* Gets the static value of an expression if it can be determined

366

* @param node - Expression node to evaluate

367

* @param initialScope - Optional initial scope for evaluation

368

* @returns Object with value and whether it's static, or null

369

*/

370

function getStaticValue(

371

node: TSESTree.Node,

372

initialScope?: TSESLintScope.Scope

373

): { value: unknown; static: boolean } | null;

374

375

/**

376

* Gets string value if the expression evaluates to a constant string

377

* @param node - Expression node to evaluate

378

* @param initialScope - Optional initial scope for evaluation

379

* @returns String value or null if not a constant string

380

*/

381

function getStringIfConstant(

382

node: TSESTree.Node,

383

initialScope?: TSESLintScope.Scope

384

): string | null;

385

386

/**

387

* Checks if a node has side effects when executed

388

* @param node - Node to check for side effects

389

* @param sourceCode - Source code object for analysis

390

* @param options - Optional configuration for side effect analysis

391

* @returns True if the node may have side effects

392

*/

393

function hasSideEffect(

394

node: TSESTree.Node,

395

sourceCode: TSESLint.SourceCode,

396

options?: { considerGetters?: boolean; considerImplicitTypeConversion?: boolean }

397

): boolean;

398

399

/**

400

* Checks if a node is wrapped in parentheses

401

* @param node - Node to check

402

* @param sourceCode - Source code object

403

* @returns True if the node is parenthesized

404

*/

405

function isParenthesized(

406

node: TSESTree.Node,

407

sourceCode: TSESLint.SourceCode

408

): boolean;

409

```

410

411

### Pattern Matching

412

413

Advanced pattern matching utilities for complex AST analysis.

414

415

```typescript { .api }

416

/**

417

* Pattern matcher class for advanced string pattern matching with escape sequences

418

*/

419

class PatternMatcher {

420

/**

421

* Creates a new pattern matcher

422

* @param pattern - Pattern string with escape sequences

423

* @param options - Optional configuration

424

*/

425

constructor(pattern: string, options?: { unicode?: boolean; sticky?: boolean });

426

427

/**

428

* Executes the pattern against input and returns all matches

429

* @param input - Input string to match against

430

* @returns Array of match results

431

*/

432

execAll(input: string): RegExpExecArray[];

433

434

/**

435

* Tests if the pattern matches the input

436

* @param input - Input string to test

437

* @returns True if pattern matches

438

*/

439

test(input: string): boolean;

440

441

/**

442

* Symbol.replace implementation for use with String.replace()

443

*/

444

[Symbol.replace](input: string, replacement: string): string;

445

}

446

```

447

448

### Reference Tracking

449

450

Utilities for tracking variable and import references across scopes.

451

452

```typescript { .api }

453

/**

454

* Reference tracker for following imports and variable usage

455

*/

456

class ReferenceTracker {

457

/**

458

* Creates a new reference tracker

459

* @param globalScope - Global scope to start tracking from

460

*/

461

constructor(globalScope: TSESLintScope.GlobalScope);

462

463

/**

464

* Iterates over global references

465

* @param traceMap - Map of global references to trace

466

* @returns Iterator of found references

467

*/

468

iterateGlobalReferences<T>(

469

traceMap: ReferenceTracker.TraceMap<T>

470

): IterableIterator<ReferenceTracker.FoundReference<T>>;

471

472

/**

473

* Iterates over CommonJS references

474

* @param traceMap - Map of CJS references to trace

475

* @returns Iterator of found references

476

*/

477

iterateCjsReferences<T>(

478

traceMap: ReferenceTracker.TraceMap<T>

479

): IterableIterator<ReferenceTracker.FoundReference<T>>;

480

481

/**

482

* Iterates over ESM references

483

* @param traceMap - Map of ESM references to trace

484

* @returns Iterator of found references

485

*/

486

iterateEsmReferences<T>(

487

traceMap: ReferenceTracker.TraceMap<T>

488

): IterableIterator<ReferenceTracker.FoundReference<T>>;

489

}

490

491

namespace ReferenceTracker {

492

const READ: unique symbol; // Read reference type

493

const CALL: unique symbol; // Call reference type

494

const CONSTRUCT: unique symbol; // Constructor reference type

495

const ESM: unique symbol; // ESM import type

496

497

interface TraceMap<T> {

498

[key: string]: TraceMapElement<T>;

499

}

500

501

type TraceMapElement<T> =

502

| T

503

| { [READ]?: T }

504

| { [CALL]?: T }

505

| { [CONSTRUCT]?: T }

506

| { [ESM]?: true }

507

| TraceMap<T>;

508

509

interface FoundReference<T> {

510

node: TSESTree.Node;

511

path: readonly string[];

512

type: typeof READ | typeof CALL | typeof CONSTRUCT;

513

info: T;

514

}

515

}

516

```

517

518

### Scope Analysis Helpers

519

520

Utilities for working with variable scopes and finding variables.

521

522

```typescript { .api }

523

/**

524

* Finds a variable in the given scope or parent scopes

525

* @param initialScope - Scope to start searching from

526

* @param nameOrNode - Variable name string or identifier node

527

* @returns Variable object if found, null otherwise

528

*/

529

function findVariable(

530

initialScope: TSESLintScope.Scope,

531

nameOrNode: TSESTree.Identifier | string

532

): TSESLintScope.Variable | null;

533

534

/**

535

* Gets the innermost scope that contains the given node

536

* @param initialScope - Scope to start searching from

537

* @param node - AST node to find scope for

538

* @returns Innermost scope containing the node

539

*/

540

function getInnermostScope(

541

initialScope: TSESLintScope.Scope,

542

node: TSESTree.Node

543

): TSESLintScope.Scope;

544

```

545

546

## Usage Examples

547

548

```typescript

549

import { ASTUtils, TSESTree, TSESLint } from "@typescript-eslint/experimental-utils";

550

551

// Using type guards

552

function checkNode(node: TSESTree.Node): void {

553

if (ASTUtils.isFunction(node)) {

554

// node is now typed as TSESTree.FunctionLike

555

console.log('Found function:', node.type);

556

}

557

558

if (ASTUtils.isNodeOfType(TSESTree.AST_NODE_TYPES.CallExpression)(node)) {

559

// node is now typed as TSESTree.CallExpression

560

console.log('Found call expression');

561

}

562

}

563

564

// Using predicates in a rule

565

const rule: TSESLint.RuleModule<'error', []> = {

566

meta: {

567

type: 'problem',

568

messages: { error: 'Message' },

569

schema: []

570

},

571

create(context) {

572

return {

573

CallExpression(node) {

574

if (ASTUtils.isOptionalCallExpression(node)) {

575

context.report({ node, messageId: 'error' });

576

}

577

}

578

};

579

}

580

};

581

582

// Using pattern matching

583

const matcher = new ASTUtils.PatternMatcher('console\\.log\\((.*)\\)');

584

const matches = matcher.execAll(sourceCode);

585

586

// Using reference tracking

587

const tracker = new ASTUtils.ReferenceTracker(context.getScope());

588

const traceMap = {

589

console: {

590

log: { [ASTUtils.ReferenceTracker.CALL]: true }

591

}

592

};

593

594

for (const { node } of tracker.iterateGlobalReferences(traceMap)) {

595

context.report({ node, messageId: 'error' });

596

}

597

```