CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-tsutils

Utility functions for working with TypeScript's Abstract Syntax Tree (AST) and type system

Pending
Overview
Eval results
Files

code-analysis.mddocs/

Code Analysis and Utilities

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.

Capabilities

Modifier Analysis

Utilities for analyzing TypeScript modifiers on declarations and class members.

/**
 * Get specific modifier from a node
 * @param node - Node to check for modifier
 * @param kind - Type of modifier to find
 * @returns Modifier node if found, undefined otherwise
 */
function getModifier(node: ts.Node, kind: ts.Modifier['kind']): ts.Modifier | undefined;

/**
 * Check if node has any of the specified modifiers
 * @param modifiers - Modifiers array to check
 * @param kinds - Modifier kinds to look for
 * @returns true if any of the specified modifiers are present
 */
function hasModifier(modifiers: ts.ModifiersArray | undefined, ...kinds: Array<ts.Modifier['kind']>): boolean;

/**
 * Check if parameter declaration is a parameter property
 * @param node - Parameter declaration to check
 * @returns true if parameter has access modifier making it a property
 */
function isParameterProperty(node: ts.ParameterDeclaration): boolean;

/**
 * Check if node has access modifier (public, private, protected)
 * @param node - Class element or parameter to check
 * @returns true if node has access modifier
 */
function hasAccessModifier(node: ts.ClassElement | ts.ParameterDeclaration): boolean;

/**
 * Check if parameter is the 'this' parameter
 * @param parameter - Parameter declaration to check
 * @returns true if parameter represents 'this'
 */
function isThisParameter(parameter: ts.ParameterDeclaration): boolean;

Flag Checking Utilities

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

/**
 * Check if node has specific node flags set
 * @param node - Node to check
 * @param flag - Node flags to test
 * @returns true if flags are set
 */
const isNodeFlagSet: (node: ts.Node, flag: ts.NodeFlags) => boolean;

/**
 * Check if type has specific type flags set
 * @param type - Type to check
 * @param flag - Type flags to test
 * @returns true if flags are set
 */
const isTypeFlagSet: (type: ts.Type, flag: ts.TypeFlags) => boolean;

/**
 * Check if symbol has specific symbol flags set
 * @param symbol - Symbol to check
 * @param flag - Symbol flags to test
 * @returns true if flags are set
 */
const isSymbolFlagSet: (symbol: ts.Symbol, flag: ts.SymbolFlags) => boolean;

/**
 * Check if object type has specific object flags set
 * @param objectType - Object type to check
 * @param flag - Object flags to test
 * @returns true if flags are set
 */
function isObjectFlagSet(objectType: ts.ObjectType, flag: ts.ObjectFlags): boolean;

/**
 * Check if node has specific modifier flags set
 * @param node - Node to check
 * @param flag - Modifier flags to test
 * @returns true if flags are set
 */
function isModifierFlagSet(node: ts.Node, flag: ts.ModifierFlags): boolean;

Variable Declaration Analysis

Utilities for analyzing variable declarations and their scoping behavior.

/**
 * Get the declaration kind (var, let, const) for a variable declaration list
 * @param declarationList - Variable declaration list to analyze
 * @returns Declaration kind enum value
 */
function getVariableDeclarationKind(declarationList: ts.VariableDeclarationList): VariableDeclarationKind;

/**
 * Check if variable declaration list is block-scoped (let/const)
 * @param declarationList - Declaration list to check
 * @returns true if declarations are block-scoped
 */
function isBlockScopedVariableDeclarationList(declarationList: ts.VariableDeclarationList): boolean;

/**
 * Check if variable declaration is block-scoped
 * @param declaration - Variable declaration to check
 * @returns true if declaration is block-scoped
 */
function isBlockScopedVariableDeclaration(declaration: ts.VariableDeclaration): boolean;

/**
 * Check if statement is a block-scoped declaration statement
 * @param statement - Statement to check
 * @returns true if statement declares block-scoped variables
 */
function isBlockScopedDeclarationStatement(statement: ts.Statement): statement is ts.DeclarationStatement;

/**
 * Variable declaration kind enumeration
 */
enum VariableDeclarationKind {
  Var,
  Let,
  Const
}

Destructuring Analysis

Utilities for analyzing destructuring patterns and extracting identifiers.

/**
 * Iterate through all identifiers in a destructuring pattern
 * @param pattern - Binding pattern to analyze
 * @param fn - Callback function for each identifier
 * @returns Result from callback if any
 */
function forEachDestructuringIdentifier<T>(
  pattern: ts.BindingPattern, 
  fn: (element: ts.BindingElement & { name: ts.Identifier }) => T
): T | undefined;

/**
 * Iterate through all declared variables in a declaration list
 * @param declarationList - Variable declaration list to analyze
 * @param cb - Callback function for each declared variable
 * @returns Result from callback if any
 */
function forEachDeclaredVariable<T>(
  declarationList: ts.VariableDeclarationList, 
  cb: (element: (ts.VariableDeclaration | ts.BindingElement) & { name: ts.Identifier }) => T
): T | undefined;

/**
 * Get the declaration that contains a binding element
 * @param node - Binding element to find declaration for
 * @returns Parent variable or parameter declaration
 */
function getDeclarationOfBindingElement(node: ts.BindingElement): ts.VariableDeclaration | ts.ParameterDeclaration;

Scope Analysis

Utilities for analyzing scope boundaries and context in TypeScript code.

/**
 * Determine the type of scope boundary a node represents
 * @param node - Node to check
 * @returns Scope boundary flags
 */
function isScopeBoundary(node: ts.Node): ScopeBoundary;

/**
 * Check if node is a type scope boundary
 * @param node - Node to check
 * @returns Type scope boundary flags
 */
function isTypeScopeBoundary(node: ts.Node): ScopeBoundary;

/**
 * Check if node is a function scope boundary
 * @param node - Node to check
 * @returns Function scope boundary flags
 */
function isFunctionScopeBoundary(node: ts.Node): ScopeBoundary;

/**
 * Check if node is a block scope boundary
 * @param node - Node to check
 * @returns Block scope boundary flags
 */
function isBlockScopeBoundary(node: ts.Node): ScopeBoundary;

/**
 * Check if statement is in single statement context (if/else/while body)
 * @param statement - Statement to check
 * @returns true if statement is not in block context
 */
function isInSingleStatementContext(statement: ts.Statement): boolean;

/**
 * Scope boundary enumeration
 */
enum ScopeBoundary {
  None = 0,
  Function = 1,
  Block = 2,
  Type = 4,
  ConditionalType = 8
}

/**
 * Scope boundary selector for hierarchical selection
 */
enum ScopeBoundarySelector {
  Function = ScopeBoundary.Function,
  Block = ScopeBoundarySelector.Function | ScopeBoundary.Block,
  Type = ScopeBoundarySelector.Block | ScopeBoundary.Type,
  InferType = ScopeBoundary.ConditionalType
}

Import/Export Analysis

Utilities for analyzing module import and export patterns.

/**
 * Find all import string literals in a source file
 * @param sourceFile - Source file to analyze
 * @param kinds - Types of imports to find
 * @param ignoreFileName - Whether to ignore filename-based imports
 * @returns Array of import string literals
 */
function findImports(
  sourceFile: ts.SourceFile, 
  kinds: ImportKind, 
  ignoreFileName?: boolean
): Array<ts.StringLiteral | ts.NoSubstitutionTemplateLiteral>;

/**
 * Find all import-like nodes in a source file
 * @param sourceFile - Source file to analyze
 * @param kinds - Types of imports to find
 * @param ignoreFileName - Whether to ignore filename-based imports
 * @returns Array of import-like nodes
 */
function findImportLikeNodes(
  sourceFile: ts.SourceFile, 
  kinds: ImportKind, 
  ignoreFileName?: boolean
): ImportLike[];

/**
 * Union type for import-like constructs
 */
type ImportLike = ts.ImportDeclaration 
  | ts.ImportEqualsDeclaration & {moduleReference: ts.ExternalModuleReference}
  | ts.ExportDeclaration & {moduleSpecifier: {}}
  | ts.CallExpression & {expression: ts.Token<ts.SyntaxKind.ImportKeyword> | ts.Identifier & {text: 'require'}, arguments: [ts.Expression, ...ts.Expression[]]}
  | ts.ImportTypeNode;

/**
 * Import kind enumeration for filtering import types
 */
enum ImportKind {
  ImportDeclaration = 1,
  ImportEquals = 2,
  ExportFrom = 4,
  DynamicImport = 8,
  Require = 16,
  ImportType = 32,
  All = ImportDeclaration | ImportEquals | ExportFrom | DynamicImport | Require | ImportType
}

Function and Context Analysis

Utilities for analyzing function contexts and this references.

/**
 * Check if node has its own 'this' reference
 * @param node - Node to check
 * @returns true if node establishes its own 'this' context
 */
function hasOwnThisReference(node: ts.Node): boolean;

/**
 * Check if node is a function with a body
 * @param node - Node to check
 * @returns true if node is function-like with body property
 */
function isFunctionWithBody(node: ts.Node): node is ts.FunctionLikeDeclaration & {body: {}};

/**
 * Get IIFE (Immediately Invoked Function Expression) call expression
 * @param func - Function expression or arrow function
 * @returns Call expression if function is immediately invoked
 */
function getIIFE(func: ts.FunctionExpression | ts.ArrowFunction): ts.CallExpression | undefined;

Compiler Options Analysis

Utilities for checking compiler options and their effects.

/**
 * Check if strict compiler option is enabled
 * @param options - Compiler options to check
 * @param option - Specific strict option to check
 * @returns true if strict option is enabled
 */
function isStrictCompilerOptionEnabled(options: ts.CompilerOptions, option: StrictCompilerOption): boolean;

/**
 * Check if boolean compiler option is enabled
 * @param options - Compiler options to check
 * @param option - Boolean option to check
 * @returns true if option is enabled
 */
function isCompilerOptionEnabled(options: ts.CompilerOptions, option: BooleanCompilerOptions | 'stripInternal'): boolean;

/**
 * Type for strict compiler options
 */
type StrictCompilerOption = 'noImplicitAny' | 'noImplicitThis' | 'strictNullChecks' | 'strictFunctionTypes' | 'strictPropertyInitialization' | 'alwaysStrict' | 'strictBindCallApply';

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

Ambient Context Analysis

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

/**
 * Check if statement is in ambient context
 * @param node - Statement to check
 * @returns true if statement is in ambient (declare) context
 */
function isStatementInAmbientContext(node: ts.Statement): boolean;

/**
 * Check if node is an ambient module block
 * @param node - Node to check
 * @returns true if node is ambient module block
 */
function isAmbientModuleBlock(node: ts.Node): node is ts.ModuleBlock;

/**
 * Check if module declaration is ambient
 * @param node - Module declaration to check
 * @returns true if module is ambient
 */
function isAmbientModule(node: ts.ModuleDeclaration): boolean;

Usage Examples:

import * as ts from "typescript";
import { 
  hasModifier, 
  isParameterProperty, 
  getVariableDeclarationKind,
  isScopeBoundary,
  findImports,
  isStrictCompilerOptionEnabled,
  VariableDeclarationKind,
  ScopeBoundary,
  ImportKind
} from "tsutils/util";

// Modifier analysis example
function analyzeClassMember(member: ts.ClassElement) {
  if (hasModifier(member.modifiers, ts.SyntaxKind.PrivateKeyword)) {
    console.log("Member is private");
  }
  
  if (hasModifier(member.modifiers, ts.SyntaxKind.StaticKeyword, ts.SyntaxKind.ReadonlyKeyword)) {
    console.log("Member is static or readonly");
  }
}

// Parameter property detection
function analyzeConstructorParameters(constructor: ts.ConstructorDeclaration) {
  constructor.parameters.forEach(param => {
    if (isParameterProperty(param)) {
      console.log(`Parameter ${param.name?.getText()} is also a property`);
    }
  });
}

// Variable declaration analysis
function analyzeVariableDeclarations(statement: ts.VariableStatement) {
  const kind = getVariableDeclarationKind(statement.declarationList);
  
  switch (kind) {
    case VariableDeclarationKind.Var:
      console.log("Function-scoped variables");
      break;
    case VariableDeclarationKind.Let:
      console.log("Block-scoped mutable variables");
      break;
    case VariableDeclarationKind.Const:
      console.log("Block-scoped immutable variables");
      break;
  }
}

// Scope boundary analysis
function analyzeScopeBoundaries(node: ts.Node) {
  const boundary = isScopeBoundary(node);
  
  if (boundary & ScopeBoundary.Function) {
    console.log("Node creates function scope");
  }
  
  if (boundary & ScopeBoundary.Block) {
    console.log("Node creates block scope");
  }
  
  if (boundary & ScopeBoundary.Type) {
    console.log("Node creates type scope");
  }
}

// Import analysis
function analyzeImports(sourceFile: ts.SourceFile) {
  const allImports = findImports(sourceFile, ImportKind.All);
  const dynamicImports = findImports(sourceFile, ImportKind.DynamicImport);
  
  console.log(`Total imports: ${allImports.length}`);
  console.log(`Dynamic imports: ${dynamicImports.length}`);
  
  allImports.forEach(importLiteral => {
    console.log(`Import: ${importLiteral.text}`);
  });
}

// Compiler options checking
function checkStrictMode(options: ts.CompilerOptions) {
  if (isStrictCompilerOptionEnabled(options, 'strictNullChecks')) {
    console.log("Strict null checks enabled");
  }
  
  if (isStrictCompilerOptionEnabled(options, 'noImplicitAny')) {
    console.log("No implicit any enabled");
  }
}

Install with Tessl CLI

npx tessl i tessl/npm-tsutils

docs

ast-traversal.md

code-analysis.md

control-flow.md

index.md

node-typeguards.md

text-processing.md

type-guards.md

type-utilities.md

variable-usage.md

tile.json