or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

ast-traversal.mdcode-analysis.mdcontrol-flow.mdindex.mdnode-typeguards.mdtext-processing.mdtype-guards.mdtype-utilities.mdvariable-usage.md

code-analysis.mddocs/

0

# Code Analysis and Utilities

1

2

Advanced analysis utilities for scope boundaries, variable declarations, control flow, import/export analysis, modifier checking, and compiler option validation. These functions provide deep insights into TypeScript code structure and behavior.

3

4

## Capabilities

5

6

### Modifier Analysis

7

8

Utilities for analyzing TypeScript modifiers on declarations and class members.

9

10

```typescript { .api }

11

/**

12

* Get specific modifier from a node

13

* @param node - Node to check for modifier

14

* @param kind - Type of modifier to find

15

* @returns Modifier node if found, undefined otherwise

16

*/

17

function getModifier(node: ts.Node, kind: ts.Modifier['kind']): ts.Modifier | undefined;

18

19

/**

20

* Check if node has any of the specified modifiers

21

* @param modifiers - Modifiers array to check

22

* @param kinds - Modifier kinds to look for

23

* @returns true if any of the specified modifiers are present

24

*/

25

function hasModifier(modifiers: ts.ModifiersArray | undefined, ...kinds: Array<ts.Modifier['kind']>): boolean;

26

27

/**

28

* Check if parameter declaration is a parameter property

29

* @param node - Parameter declaration to check

30

* @returns true if parameter has access modifier making it a property

31

*/

32

function isParameterProperty(node: ts.ParameterDeclaration): boolean;

33

34

/**

35

* Check if node has access modifier (public, private, protected)

36

* @param node - Class element or parameter to check

37

* @returns true if node has access modifier

38

*/

39

function hasAccessModifier(node: ts.ClassElement | ts.ParameterDeclaration): boolean;

40

41

/**

42

* Check if parameter is the 'this' parameter

43

* @param parameter - Parameter declaration to check

44

* @returns true if parameter represents 'this'

45

*/

46

function isThisParameter(parameter: ts.ParameterDeclaration): boolean;

47

```

48

49

### Flag Checking Utilities

50

51

Utilities for checking various TypeScript compiler flags on nodes, types, and symbols.

52

53

```typescript { .api }

54

/**

55

* Check if node has specific node flags set

56

* @param node - Node to check

57

* @param flag - Node flags to test

58

* @returns true if flags are set

59

*/

60

const isNodeFlagSet: (node: ts.Node, flag: ts.NodeFlags) => boolean;

61

62

/**

63

* Check if type has specific type flags set

64

* @param type - Type to check

65

* @param flag - Type flags to test

66

* @returns true if flags are set

67

*/

68

const isTypeFlagSet: (type: ts.Type, flag: ts.TypeFlags) => boolean;

69

70

/**

71

* Check if symbol has specific symbol flags set

72

* @param symbol - Symbol to check

73

* @param flag - Symbol flags to test

74

* @returns true if flags are set

75

*/

76

const isSymbolFlagSet: (symbol: ts.Symbol, flag: ts.SymbolFlags) => boolean;

77

78

/**

79

* Check if object type has specific object flags set

80

* @param objectType - Object type to check

81

* @param flag - Object flags to test

82

* @returns true if flags are set

83

*/

84

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

85

86

/**

87

* Check if node has specific modifier flags set

88

* @param node - Node to check

89

* @param flag - Modifier flags to test

90

* @returns true if flags are set

91

*/

92

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

93

```

94

95

### Variable Declaration Analysis

96

97

Utilities for analyzing variable declarations and their scoping behavior.

98

99

```typescript { .api }

100

/**

101

* Get the declaration kind (var, let, const) for a variable declaration list

102

* @param declarationList - Variable declaration list to analyze

103

* @returns Declaration kind enum value

104

*/

105

function getVariableDeclarationKind(declarationList: ts.VariableDeclarationList): VariableDeclarationKind;

106

107

/**

108

* Check if variable declaration list is block-scoped (let/const)

109

* @param declarationList - Declaration list to check

110

* @returns true if declarations are block-scoped

111

*/

112

function isBlockScopedVariableDeclarationList(declarationList: ts.VariableDeclarationList): boolean;

113

114

/**

115

* Check if variable declaration is block-scoped

116

* @param declaration - Variable declaration to check

117

* @returns true if declaration is block-scoped

118

*/

119

function isBlockScopedVariableDeclaration(declaration: ts.VariableDeclaration): boolean;

120

121

/**

122

* Check if statement is a block-scoped declaration statement

123

* @param statement - Statement to check

124

* @returns true if statement declares block-scoped variables

125

*/

126

function isBlockScopedDeclarationStatement(statement: ts.Statement): statement is ts.DeclarationStatement;

127

128

/**

129

* Variable declaration kind enumeration

130

*/

131

enum VariableDeclarationKind {

132

Var,

133

Let,

134

Const

135

}

136

```

137

138

### Destructuring Analysis

139

140

Utilities for analyzing destructuring patterns and extracting identifiers.

141

142

```typescript { .api }

143

/**

144

* Iterate through all identifiers in a destructuring pattern

145

* @param pattern - Binding pattern to analyze

146

* @param fn - Callback function for each identifier

147

* @returns Result from callback if any

148

*/

149

function forEachDestructuringIdentifier<T>(

150

pattern: ts.BindingPattern,

151

fn: (element: ts.BindingElement & { name: ts.Identifier }) => T

152

): T | undefined;

153

154

/**

155

* Iterate through all declared variables in a declaration list

156

* @param declarationList - Variable declaration list to analyze

157

* @param cb - Callback function for each declared variable

158

* @returns Result from callback if any

159

*/

160

function forEachDeclaredVariable<T>(

161

declarationList: ts.VariableDeclarationList,

162

cb: (element: (ts.VariableDeclaration | ts.BindingElement) & { name: ts.Identifier }) => T

163

): T | undefined;

164

165

/**

166

* Get the declaration that contains a binding element

167

* @param node - Binding element to find declaration for

168

* @returns Parent variable or parameter declaration

169

*/

170

function getDeclarationOfBindingElement(node: ts.BindingElement): ts.VariableDeclaration | ts.ParameterDeclaration;

171

```

172

173

### Scope Analysis

174

175

Utilities for analyzing scope boundaries and context in TypeScript code.

176

177

```typescript { .api }

178

/**

179

* Determine the type of scope boundary a node represents

180

* @param node - Node to check

181

* @returns Scope boundary flags

182

*/

183

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

184

185

/**

186

* Check if node is a type scope boundary

187

* @param node - Node to check

188

* @returns Type scope boundary flags

189

*/

190

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

191

192

/**

193

* Check if node is a function scope boundary

194

* @param node - Node to check

195

* @returns Function scope boundary flags

196

*/

197

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

198

199

/**

200

* Check if node is a block scope boundary

201

* @param node - Node to check

202

* @returns Block scope boundary flags

203

*/

204

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

205

206

/**

207

* Check if statement is in single statement context (if/else/while body)

208

* @param statement - Statement to check

209

* @returns true if statement is not in block context

210

*/

211

function isInSingleStatementContext(statement: ts.Statement): boolean;

212

213

/**

214

* Scope boundary enumeration

215

*/

216

enum ScopeBoundary {

217

None = 0,

218

Function = 1,

219

Block = 2,

220

Type = 4,

221

ConditionalType = 8

222

}

223

224

/**

225

* Scope boundary selector for hierarchical selection

226

*/

227

enum ScopeBoundarySelector {

228

Function = ScopeBoundary.Function,

229

Block = ScopeBoundarySelector.Function | ScopeBoundary.Block,

230

Type = ScopeBoundarySelector.Block | ScopeBoundary.Type,

231

InferType = ScopeBoundary.ConditionalType

232

}

233

```

234

235

### Import/Export Analysis

236

237

Utilities for analyzing module import and export patterns.

238

239

```typescript { .api }

240

/**

241

* Find all import string literals in a source file

242

* @param sourceFile - Source file to analyze

243

* @param kinds - Types of imports to find

244

* @param ignoreFileName - Whether to ignore filename-based imports

245

* @returns Array of import string literals

246

*/

247

function findImports(

248

sourceFile: ts.SourceFile,

249

kinds: ImportKind,

250

ignoreFileName?: boolean

251

): Array<ts.StringLiteral | ts.NoSubstitutionTemplateLiteral>;

252

253

/**

254

* Find all import-like nodes in a source file

255

* @param sourceFile - Source file to analyze

256

* @param kinds - Types of imports to find

257

* @param ignoreFileName - Whether to ignore filename-based imports

258

* @returns Array of import-like nodes

259

*/

260

function findImportLikeNodes(

261

sourceFile: ts.SourceFile,

262

kinds: ImportKind,

263

ignoreFileName?: boolean

264

): ImportLike[];

265

266

/**

267

* Union type for import-like constructs

268

*/

269

type ImportLike = ts.ImportDeclaration

270

| ts.ImportEqualsDeclaration & {moduleReference: ts.ExternalModuleReference}

271

| ts.ExportDeclaration & {moduleSpecifier: {}}

272

| ts.CallExpression & {expression: ts.Token<ts.SyntaxKind.ImportKeyword> | ts.Identifier & {text: 'require'}, arguments: [ts.Expression, ...ts.Expression[]]}

273

| ts.ImportTypeNode;

274

275

/**

276

* Import kind enumeration for filtering import types

277

*/

278

enum ImportKind {

279

ImportDeclaration = 1,

280

ImportEquals = 2,

281

ExportFrom = 4,

282

DynamicImport = 8,

283

Require = 16,

284

ImportType = 32,

285

All = ImportDeclaration | ImportEquals | ExportFrom | DynamicImport | Require | ImportType

286

}

287

```

288

289

### Function and Context Analysis

290

291

Utilities for analyzing function contexts and this references.

292

293

```typescript { .api }

294

/**

295

* Check if node has its own 'this' reference

296

* @param node - Node to check

297

* @returns true if node establishes its own 'this' context

298

*/

299

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

300

301

/**

302

* Check if node is a function with a body

303

* @param node - Node to check

304

* @returns true if node is function-like with body property

305

*/

306

function isFunctionWithBody(node: ts.Node): node is ts.FunctionLikeDeclaration & {body: {}};

307

308

/**

309

* Get IIFE (Immediately Invoked Function Expression) call expression

310

* @param func - Function expression or arrow function

311

* @returns Call expression if function is immediately invoked

312

*/

313

function getIIFE(func: ts.FunctionExpression | ts.ArrowFunction): ts.CallExpression | undefined;

314

```

315

316

### Compiler Options Analysis

317

318

Utilities for checking compiler options and their effects.

319

320

```typescript { .api }

321

/**

322

* Check if strict compiler option is enabled

323

* @param options - Compiler options to check

324

* @param option - Specific strict option to check

325

* @returns true if strict option is enabled

326

*/

327

function isStrictCompilerOptionEnabled(options: ts.CompilerOptions, option: StrictCompilerOption): boolean;

328

329

/**

330

* Check if boolean compiler option is enabled

331

* @param options - Compiler options to check

332

* @param option - Boolean option to check

333

* @returns true if option is enabled

334

*/

335

function isCompilerOptionEnabled(options: ts.CompilerOptions, option: BooleanCompilerOptions | 'stripInternal'): boolean;

336

337

/**

338

* Type for strict compiler options

339

*/

340

type StrictCompilerOption = 'noImplicitAny' | 'noImplicitThis' | 'strictNullChecks' | 'strictFunctionTypes' | 'strictPropertyInitialization' | 'alwaysStrict' | 'strictBindCallApply';

341

342

/**

343

* Type for boolean compiler options

344

*/

345

type BooleanCompilerOptions = {[K in keyof ts.CompilerOptions]: NonNullable<ts.CompilerOptions[K]> extends boolean ? K : never} extends {[_ in keyof ts.CompilerOptions]: infer U} ? U : never;

346

```

347

348

### Ambient Context Analysis

349

350

Utilities for analyzing ambient (declare) contexts and module blocks.

351

352

```typescript { .api }

353

/**

354

* Check if statement is in ambient context

355

* @param node - Statement to check

356

* @returns true if statement is in ambient (declare) context

357

*/

358

function isStatementInAmbientContext(node: ts.Statement): boolean;

359

360

/**

361

* Check if node is an ambient module block

362

* @param node - Node to check

363

* @returns true if node is ambient module block

364

*/

365

function isAmbientModuleBlock(node: ts.Node): node is ts.ModuleBlock;

366

367

/**

368

* Check if module declaration is ambient

369

* @param node - Module declaration to check

370

* @returns true if module is ambient

371

*/

372

function isAmbientModule(node: ts.ModuleDeclaration): boolean;

373

```

374

375

**Usage Examples:**

376

377

```typescript

378

import * as ts from "typescript";

379

import {

380

hasModifier,

381

isParameterProperty,

382

getVariableDeclarationKind,

383

isScopeBoundary,

384

findImports,

385

isStrictCompilerOptionEnabled,

386

VariableDeclarationKind,

387

ScopeBoundary,

388

ImportKind

389

} from "tsutils/util";

390

391

// Modifier analysis example

392

function analyzeClassMember(member: ts.ClassElement) {

393

if (hasModifier(member.modifiers, ts.SyntaxKind.PrivateKeyword)) {

394

console.log("Member is private");

395

}

396

397

if (hasModifier(member.modifiers, ts.SyntaxKind.StaticKeyword, ts.SyntaxKind.ReadonlyKeyword)) {

398

console.log("Member is static or readonly");

399

}

400

}

401

402

// Parameter property detection

403

function analyzeConstructorParameters(constructor: ts.ConstructorDeclaration) {

404

constructor.parameters.forEach(param => {

405

if (isParameterProperty(param)) {

406

console.log(`Parameter ${param.name?.getText()} is also a property`);

407

}

408

});

409

}

410

411

// Variable declaration analysis

412

function analyzeVariableDeclarations(statement: ts.VariableStatement) {

413

const kind = getVariableDeclarationKind(statement.declarationList);

414

415

switch (kind) {

416

case VariableDeclarationKind.Var:

417

console.log("Function-scoped variables");

418

break;

419

case VariableDeclarationKind.Let:

420

console.log("Block-scoped mutable variables");

421

break;

422

case VariableDeclarationKind.Const:

423

console.log("Block-scoped immutable variables");

424

break;

425

}

426

}

427

428

// Scope boundary analysis

429

function analyzeScopeBoundaries(node: ts.Node) {

430

const boundary = isScopeBoundary(node);

431

432

if (boundary & ScopeBoundary.Function) {

433

console.log("Node creates function scope");

434

}

435

436

if (boundary & ScopeBoundary.Block) {

437

console.log("Node creates block scope");

438

}

439

440

if (boundary & ScopeBoundary.Type) {

441

console.log("Node creates type scope");

442

}

443

}

444

445

// Import analysis

446

function analyzeImports(sourceFile: ts.SourceFile) {

447

const allImports = findImports(sourceFile, ImportKind.All);

448

const dynamicImports = findImports(sourceFile, ImportKind.DynamicImport);

449

450

console.log(`Total imports: ${allImports.length}`);

451

console.log(`Dynamic imports: ${dynamicImports.length}`);

452

453

allImports.forEach(importLiteral => {

454

console.log(`Import: ${importLiteral.text}`);

455

});

456

}

457

458

// Compiler options checking

459

function checkStrictMode(options: ts.CompilerOptions) {

460

if (isStrictCompilerOptionEnabled(options, 'strictNullChecks')) {

461

console.log("Strict null checks enabled");

462

}

463

464

if (isStrictCompilerOptionEnabled(options, 'noImplicitAny')) {

465

console.log("No implicit any enabled");

466

}

467

}

468

```