or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

tessl/npm-ts-api-utils

Utility functions for working with TypeScript's API, providing comprehensive tools for analyzing and manipulating TypeScript AST nodes, types, and compiler APIs.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/ts-api-utils@2.0.x

To install, run

npx @tessl/cli install tessl/npm-ts-api-utils@2.0.0

0

# ts-api-utils

1

2

A comprehensive collection of utility functions for working with TypeScript's API. This library serves as the successor to the popular `tsutils` library, providing a modern, well-typed toolkit for building TypeScript tooling, linters, code analyzers, and other developer tools that need to work with TypeScript's Abstract Syntax Tree (AST).

3

4

## Package Information

5

6

- **Package Name**: `ts-api-utils`

7

- **Version**: 2.0.0

8

- **Language**: TypeScript (compiled to JavaScript)

9

- **License**: MIT

10

- **Repository**: [github.com/JoshuaKGoldberg/ts-api-utils](https://github.com/JoshuaKGoldberg/ts-api-utils)

11

- **Minimum TypeScript Version**: 4.8.4

12

- **Node Version**: >=18.12

13

14

### Installation

15

16

```bash

17

npm install ts-api-utils

18

```

19

20

### Core Imports

21

22

The library supports both ESM and CommonJS imports:

23

24

```typescript { .api }

25

// ESM import (recommended)

26

import * as tsutils from "ts-api-utils";

27

28

// Named imports

29

import {

30

forEachToken,

31

isBlockStatement,

32

getCallSignaturesOfType,

33

collectVariableUsage,

34

isTsVersionAtLeast

35

} from "ts-api-utils";

36

37

// CommonJS (legacy)

38

const tsutils = require("ts-api-utils");

39

```

40

41

## Basic Usage

42

43

ts-api-utils provides utilities that work seamlessly with TypeScript's compiler API:

44

45

```typescript { .api }

46

import * as ts from "typescript";

47

import { forEachToken, isBlockStatement, getCallSignaturesOfType } from "ts-api-utils";

48

49

// Example: Iterate over all tokens in a node

50

function analyzeNode(node: ts.Node, sourceFile: ts.SourceFile) {

51

forEachToken(node, (token) => {

52

console.log(`Token: ${ts.SyntaxKind[token.kind]}`);

53

}, sourceFile);

54

}

55

56

// Example: Type-safe node checking

57

function processStatement(node: ts.Node) {

58

if (isBlockStatement(node)) {

59

// TypeScript now knows 'node' is a BlockStatement

60

console.log(`Block has ${node.statements.length} statements`);

61

}

62

}

63

64

// Example: Working with type information

65

function analyzeType(type: ts.Type) {

66

const signatures = getCallSignaturesOfType(type);

67

if (signatures.length > 0) {

68

console.log(`Type has ${signatures.length} call signatures`);

69

}

70

}

71

```

72

73

## Architecture

74

75

ts-api-utils is organized into logical modules that mirror different aspects of TypeScript analysis:

76

77

### Core Design Patterns

78

79

1. **Type Guards**: Functions that narrow TypeScript types (e.g., `isBlockStatement`)

80

2. **Analyzers**: Functions that extract information from AST nodes (e.g., `getAccessKind`)

81

3. **Utilities**: Helper functions for common operations (e.g., `forEachToken`)

82

4. **Collectors**: Functions that gather data across larger code structures (e.g., `collectVariableUsage`)

83

84

### Module Organization

85

86

The library is structured around these main capability areas:

87

88

- **Node Analysis**: The largest module, containing type guards for every TypeScript node type

89

- **Type System Utilities**: Second largest module, providing deep integration with TypeScript's type system

90

- **Usage Analysis**: Advanced scope and variable tracking capabilities

91

- **Token Processing**: Low-level token iteration and manipulation

92

- **Syntax Utilities**: Common syntax analysis patterns

93

- **Compiler Integration**: Working with compiler options and flags

94

- **Comment Processing**: Extracting and working with code comments

95

- **Scope Analysis**: Understanding scope boundaries and relationships

96

- **Modifier Utilities**: Working with TypeScript modifiers

97

98

## Capabilities

99

100

### Comments Processing

101

102

Working with TypeScript comments attached to AST nodes.

103

104

**When to use**: Extract documentation, analyze comment patterns, or build tools that need to preserve or manipulate comments during code transformations.

105

106

```typescript { .api }

107

import { forEachComment, ForEachCommentCallback } from "ts-api-utils";

108

109

// Callback for processing each comment

110

type ForEachCommentCallback = (fullText: string, comment: ts.CommentRange) => void;

111

112

// Iterate over all comments owned by a node or its children

113

function forEachComment(

114

node: ts.Node,

115

callback: ForEachCommentCallback,

116

sourceFile?: ts.SourceFile

117

): void;

118

```

119

120

[Syntax Utilities Guide](./syntax-utilities.md)

121

122

### Compiler Options

123

124

Analyzing and testing TypeScript compiler configuration settings.

125

126

**When to use**: Build tools that need to understand compiler settings, validate configurations, or provide different behavior based on strict mode settings.

127

128

```typescript { .api }

129

import {

130

isCompilerOptionEnabled,

131

isStrictCompilerOptionEnabled,

132

BooleanCompilerOptions,

133

StrictCompilerOption

134

} from "ts-api-utils";

135

136

// Options that can be tested with isCompilerOptionEnabled

137

type BooleanCompilerOptions = keyof {

138

[K in keyof ts.CompilerOptions as NonNullable<ts.CompilerOptions[K]> extends boolean ? K : never]: unknown;

139

};

140

141

// Strict mode options

142

type StrictCompilerOption =

143

| "alwaysStrict"

144

| "noImplicitAny"

145

| "noImplicitThis"

146

| "strictBindCallApply"

147

| "strictFunctionTypes"

148

| "strictNullChecks"

149

| "strictPropertyInitialization";

150

151

// Check if a compiler option is enabled (handles option dependencies)

152

function isCompilerOptionEnabled(

153

options: ts.CompilerOptions,

154

option: BooleanCompilerOptions

155

): boolean;

156

157

// Check strict mode options (accounts for global strict setting)

158

function isStrictCompilerOptionEnabled(

159

options: ts.CompilerOptions,

160

option: StrictCompilerOption

161

): boolean;

162

```

163

164

[Compiler Options Guide](./compiler-options.md)

165

166

### Flag Utilities

167

168

Testing various TypeScript flags on nodes, types, and symbols.

169

170

**When to use**: Determine node characteristics, check type properties, or analyze symbol metadata in static analysis tools.

171

172

```typescript { .api }

173

import {

174

isModifierFlagSet,

175

isNodeFlagSet,

176

isObjectFlagSet,

177

isSymbolFlagSet,

178

isTypeFlagSet

179

} from "ts-api-utils";

180

181

// Test modifier flags on declarations

182

function isModifierFlagSet(node: ts.Declaration, flag: ts.ModifierFlags): boolean;

183

184

// Test node flags

185

function isNodeFlagSet(node: ts.Node, flag: ts.NodeFlags): boolean;

186

187

// Test object type flags

188

function isObjectFlagSet(objectType: ts.ObjectType, flag: ts.ObjectFlags): boolean;

189

190

// Test symbol flags

191

function isSymbolFlagSet(symbol: ts.Symbol, flag: ts.SymbolFlags): boolean;

192

193

// Test type flags

194

function isTypeFlagSet(type: ts.Type, flag: ts.TypeFlags): boolean;

195

```

196

197

[Flag Utilities Guide](./syntax-utilities.md)

198

199

### Modifier Utilities

200

201

Working with TypeScript modifier tokens like `public`, `private`, `static`, etc.

202

203

**When to use**: Analyze access modifiers, check for specific modifiers, or build tools that need to understand declaration visibility.

204

205

```typescript { .api }

206

import { includesModifier } from "ts-api-utils";

207

208

// Test if modifiers include any of the given kinds

209

function includesModifier(

210

modifiers: Iterable<ts.ModifierLike> | undefined,

211

...kinds: ts.ModifierSyntaxKind[]

212

): boolean;

213

```

214

215

[Modifier Utilities Guide](./syntax-utilities.md)

216

217

### Node Analysis

218

219

The most comprehensive module providing type guards and utilities for every TypeScript AST node type.

220

221

**When to use**: This is the core of most TypeScript analysis tools. Use these functions whenever you need to safely narrow node types, check node properties, or traverse the AST with type safety.

222

223

```typescript { .api }

224

import {

225

isBlockStatement,

226

isVariableDeclaration,

227

isIterationStatement,

228

isNamedDeclarationWithName,

229

isConstAssertionExpression,

230

hasModifiers,

231

hasType,

232

isAccessExpression,

233

getAccessKind,

234

AccessKind

235

} from "ts-api-utils";

236

237

// Access patterns for expressions

238

enum AccessKind {

239

None = 0,

240

Read = 1,

241

Write = 2,

242

Delete = 4,

243

ReadWrite = 3

244

}

245

246

// Type guards for compound node types

247

interface NamedDeclarationWithName extends ts.NamedDeclaration {

248

readonly name: ts.DeclarationName;

249

}

250

251

interface ConstAssertionExpression extends ts.AssertionExpression {

252

readonly type: ts.TypeNode & { readonly typeName: ConstAssertionIdentifier };

253

}

254

255

// Essential node type guards

256

function isBlockStatement(node: ts.Node): node is ts.BlockStatement;

257

function isVariableDeclaration(node: ts.Node): node is ts.VariableDeclaration;

258

function isIterationStatement(node: ts.Node): node is ts.IterationStatement;

259

function isNamedDeclarationWithName(node: ts.Declaration): node is NamedDeclarationWithName;

260

261

// Property-based type guards

262

function hasModifiers(node: ts.Node): node is ts.HasModifiers;

263

function hasType(node: ts.Node): node is ts.HasType;

264

function isAccessExpression(node: ts.Node): node is ts.AccessExpression;

265

266

// Expression analysis

267

function getAccessKind(node: ts.Expression): AccessKind;

268

```

269

270

[Node Analysis Guide](./node-analysis.md)

271

272

### Scope Analysis

273

274

Determining scope boundaries and understanding lexical scoping in TypeScript.

275

276

**When to use**: Build variable tracking tools, analyze closure behavior, or implement scope-aware refactoring tools.

277

278

```typescript { .api }

279

import { isFunctionScopeBoundary } from "ts-api-utils";

280

281

// Check if a node creates a function scope boundary

282

function isFunctionScopeBoundary(node: ts.Node): boolean;

283

```

284

285

[Scope Analysis Guide](./syntax-utilities.md)

286

287

### Syntax Utilities

288

289

General utilities for common syntax analysis patterns.

290

291

**When to use**: Validate identifiers, check assignment patterns, or analyze property access expressions.

292

293

```typescript { .api }

294

import {

295

isAssignmentKind,

296

isNumericPropertyName,

297

isValidPropertyAccess

298

} from "ts-api-utils";

299

300

// Test if a syntax kind represents assignment

301

function isAssignmentKind(kind: ts.SyntaxKind): boolean;

302

303

// Test if a string is a numeric property name

304

function isNumericPropertyName(name: string | ts.__String): boolean;

305

306

// Check if text can be used in property access expressions

307

function isValidPropertyAccess(text: string, languageVersion?: ts.ScriptTarget): boolean;

308

```

309

310

[Syntax Utilities Guide](./syntax-utilities.md)

311

312

### Token Processing

313

314

Low-level iteration and manipulation of tokens in TypeScript source code.

315

316

**When to use**: Build formatters, implement custom syntax highlighting, or perform detailed source code analysis that needs to examine every token.

317

318

```typescript { .api }

319

import { forEachToken, ForEachTokenCallback } from "ts-api-utils";

320

321

// Callback for processing each token

322

type ForEachTokenCallback = (token: ts.Node) => void;

323

324

// Iterate over all tokens of a node

325

function forEachToken(

326

node: ts.Node,

327

callback: ForEachTokenCallback,

328

sourceFile?: ts.SourceFile

329

): void;

330

```

331

332

[Token Processing Guide](./syntax-utilities.md)

333

334

### Type System Utilities

335

336

Comprehensive utilities for working with TypeScript's type system, including type analysis, type guards, and type manipulation.

337

338

**When to use**: Build type-aware linting rules, analyze type relationships, implement type-based refactoring tools, or create tools that need deep integration with TypeScript's type checker.

339

340

```typescript { .api }

341

import {

342

getCallSignaturesOfType,

343

getPropertyOfType,

344

intersectionTypeParts,

345

unionTypeParts,

346

typeParts,

347

isFalsyType,

348

isThenableType,

349

typeIsLiteral,

350

isPropertyReadonlyInType,

351

symbolHasReadonlyDeclaration,

352

isConditionalType,

353

isEnumType,

354

isIndexedAccessType,

355

isIntersectionType,

356

isUnionType,

357

isObjectType,

358

isTupleType,

359

isTypeReference,

360

isBooleanLiteralType,

361

isBigIntLiteralType,

362

isStringLiteralType,

363

isNumberLiteralType

364

} from "ts-api-utils";

365

366

// Type information retrieval

367

function getCallSignaturesOfType(type: ts.Type): readonly ts.Signature[];

368

function getPropertyOfType(type: ts.Type, name: ts.__String): ts.Symbol | undefined;

369

370

// Type decomposition utilities

371

function intersectionTypeParts(type: ts.Type): ts.Type[];

372

function unionTypeParts(type: ts.Type): ts.Type[];

373

function typeParts(type: ts.Type): ts.Type[];

374

375

// Type analysis utilities

376

function isFalsyType(type: ts.Type): boolean;

377

function isThenableType(typeChecker: ts.TypeChecker, node: ts.Node, type: ts.Type): boolean;

378

function typeIsLiteral(type: ts.Type): type is ts.LiteralType;

379

function isPropertyReadonlyInType(

380

type: ts.Type,

381

name: ts.__String,

382

typeChecker: ts.TypeChecker

383

): boolean;

384

385

// Symbol utilities

386

function symbolHasReadonlyDeclaration(symbol: ts.Symbol, typeChecker: ts.TypeChecker): boolean;

387

388

// Core type guards

389

function isConditionalType(type: ts.Type): type is ts.ConditionalType;

390

function isEnumType(type: ts.Type): type is ts.EnumType;

391

function isIndexedAccessType(type: ts.Type): type is ts.IndexedAccessType;

392

function isIntersectionType(type: ts.Type): type is ts.IntersectionType;

393

function isUnionType(type: ts.Type): type is ts.UnionType;

394

function isObjectType(type: ts.Type): type is ts.ObjectType;

395

396

// Object type utilities

397

function isTupleType(type: ts.Type): type is ts.TupleType;

398

function isTypeReference(type: ts.Type): type is ts.TypeReference;

399

400

// Literal type guards

401

function isBooleanLiteralType(type: ts.Type): type is ts.LiteralType;

402

function isBigIntLiteralType(type: ts.Type): type is ts.BigIntLiteralType;

403

function isStringLiteralType(type: ts.Type): type is ts.StringLiteralType;

404

function isNumberLiteralType(type: ts.Type): type is ts.NumberLiteralType;

405

```

406

407

[Type System Guide](./type-system.md)

408

409

### Usage Analysis

410

411

Advanced analysis of variable and symbol usage patterns, including scope tracking and declaration analysis.

412

413

**When to use**: Build unused variable detectors, implement variable renaming tools, analyze variable lifecycle, or create tools that need comprehensive understanding of identifier usage across scopes.

414

415

```typescript { .api }

416

import {

417

collectVariableUsage,

418

UsageInfo,

419

Usage,

420

DeclarationDomain,

421

UsageDomain,

422

isBlockScopeBoundary,

423

ScopeBoundary,

424

getDeclarationDomain,

425

getUsageDomain,

426

identifierToKeywordKind

427

} from "ts-api-utils";

428

429

// Usage domains (type vs value space)

430

enum DeclarationDomain {

431

Namespace = 1,

432

Type = 2,

433

Value = 4,

434

Any = 7,

435

Import = 8

436

}

437

438

enum UsageDomain {

439

Namespace = 1,

440

Type = 2,

441

Value = 4,

442

Any = 7,

443

TypeQuery = 8,

444

ValueOrNamespace = 5

445

}

446

447

// Usage tracking interfaces

448

interface Usage {

449

readonly domain: UsageDomain;

450

readonly location: ts.Identifier;

451

}

452

453

interface UsageInfo {

454

readonly declarations: ts.Identifier[];

455

readonly domain: DeclarationDomain;

456

readonly exported: boolean;

457

readonly inGlobalScope: boolean;

458

readonly uses: Usage[];

459

}

460

461

// Scope boundary analysis

462

enum ScopeBoundary {

463

None = 0,

464

Function = 1,

465

Block = 2,

466

Type = 4,

467

ConditionalType = 8

468

}

469

470

// Main usage collection function

471

function collectVariableUsage(sourceFile: ts.SourceFile): Map<ts.Identifier, UsageInfo>;

472

473

// Scope and domain analysis functions

474

function isBlockScopeBoundary(node: ts.Node): ScopeBoundary;

475

function getDeclarationDomain(node: ts.Identifier): DeclarationDomain | undefined;

476

function getUsageDomain(node: ts.Identifier): UsageDomain | undefined;

477

478

// TypeScript version compatibility utility

479

function identifierToKeywordKind(node: ts.Identifier): ts.SyntaxKind | undefined;

480

```

481

482

[Usage Analysis Guide](./usage-analysis.md)

483

484

### Utility Functions

485

486

General utility functions for TypeScript version compatibility and common operations.

487

488

**When to use**: Check TypeScript version compatibility for feature detection, or perform version-specific operations.

489

490

```typescript { .api }

491

import { isTsVersionAtLeast } from "ts-api-utils";

492

493

// Check if the current TypeScript version is at least the specified version

494

function isTsVersionAtLeast(major: number, minor?: number): boolean;

495

```

496

497

## Related Libraries

498

499

ts-api-utils works best when combined with:

500

501

- **TypeScript Compiler API**: The foundation that ts-api-utils extends

502

- **@typescript-eslint/utils**: For building ESLint rules with TypeScript support

503

- **ts-morph**: Higher-level TypeScript manipulation library

504

- **typescript**: The TypeScript compiler itself (peer dependency)

505

506

## Best Practices

507

508

1. **Always use type guards**: The library's type guards provide essential type safety when working with AST nodes

509

2. **Leverage the type system**: Functions are designed to work seamlessly with TypeScript's type inference

510

3. **Combine utilities**: Most real-world use cases benefit from combining multiple utilities (e.g., node analysis + type checking + usage analysis)

511

4. **Cache results**: For performance-critical applications, consider caching results of expensive operations like `collectVariableUsage`

512

5. **Use with source files**: Many functions work better when provided with the source file context

513

514

## Performance Considerations

515

516

- **Usage analysis**: `collectVariableUsage` is the most expensive operation; use judiciously for large files

517

- **Type operations**: Type-related utilities require a TypeChecker instance; reuse when possible

518

- **Token iteration**: `forEachToken` can be expensive for very large nodes; consider targeted analysis instead

519

- **Scope analysis**: Scope boundary detection is generally fast and safe to use liberally

520

521

ts-api-utils provides the essential building blocks for any serious TypeScript tooling project, offering both low-level token manipulation and high-level semantic analysis capabilities.