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

text-processing.mddocs/

Text Processing and Validation

Text processing utilities for source code analysis including line range calculation, identifier validation, comment extraction, position-based operations, and various text validation functions for TypeScript constructs.

Capabilities

Line Range Analysis

Utilities for analyzing line structure and line breaks in source files.

/**
 * Get line ranges for all lines in a source file
 * @param sourceFile - Source file to analyze
 * @returns Array of line ranges with position and content length information
 */
function getLineRanges(sourceFile: ts.SourceFile): LineRange[];

/**
 * Get the line break style used in a source file
 * @param sourceFile - Source file to analyze
 * @returns Line break string (e.g., '\n', '\r\n', '\r')
 */
function getLineBreakStyle(sourceFile: ts.SourceFile): string;

/**
 * Check if two positions are on the same line
 * @param sourceFile - Source file containing the positions
 * @param pos1 - First position
 * @param pos2 - Second position
 * @returns true if both positions are on the same line
 */
function isSameLine(sourceFile: ts.SourceFile, pos1: number, pos2: number): boolean;

/**
 * Line range interface with content length information
 */
interface LineRange extends ts.TextRange {
  /** Length of actual content on the line (excluding line break) */
  contentLength: number;
}

Identifier and Name Validation

Utilities for validating TypeScript identifiers and property names.

/**
 * Check if text is a valid TypeScript identifier
 * @param text - Text to validate
 * @param languageVersion - TypeScript language version (optional)
 * @returns true if text is valid identifier
 */
function isValidIdentifier(text: string, languageVersion?: ts.ScriptTarget): boolean;

/**
 * Check if text can be used as property access (obj.prop)
 * @param text - Text to validate
 * @param languageVersion - TypeScript language version (optional)
 * @returns true if text is valid for property access
 */
function isValidPropertyAccess(text: string, languageVersion?: ts.ScriptTarget): boolean;

/**
 * Check if text is a valid property name
 * @param text - Text to validate
 * @param languageVersion - TypeScript language version (optional)
 * @returns true if text is valid property name
 */
function isValidPropertyName(text: string, languageVersion?: ts.ScriptTarget): boolean;

/**
 * Check if text is a valid numeric literal
 * @param text - Text to validate
 * @param languageVersion - TypeScript language version (optional)
 * @returns true if text is valid numeric literal
 */
function isValidNumericLiteral(text: string, languageVersion?: ts.ScriptTarget): boolean;

/**
 * Check if text is a valid JSX identifier
 * @param text - Text to validate
 * @param languageVersion - TypeScript language version (optional)
 * @returns true if text is valid JSX identifier
 */
function isValidJsxIdentifier(text: string, languageVersion?: ts.ScriptTarget): boolean;

Property Name Analysis

Utilities for working with property names and numeric properties.

/**
 * Extract property name from a property name node
 * @param propertyName - Property name node
 * @returns String representation of property name or undefined if not extractable
 */
function getPropertyName(propertyName: ts.PropertyName): string | undefined;

/**
 * Check if property name is numeric
 * @param name - Property name to check
 * @returns true if name represents a numeric property
 */
function isNumericPropertyName(name: string | ts.__String): boolean;

Well-Known Symbol Analysis

Utilities for analyzing well-known symbol property access.

/**
 * Check if expression is a well-known symbol literal (Symbol.iterator, etc.)
 * @param node - Expression to check
 * @returns true if expression is well-known symbol access
 */
function isWellKnownSymbolLiterally(node: ts.Expression): node is WellKnownSymbolLiteral;

/**
 * Get property name information for well-known symbol
 * @param node - Well-known symbol literal node
 * @returns Property name information
 * @deprecated Use getLateBoundPropertyNames instead
 */
function getPropertyNameOfWellKnownSymbol(node: WellKnownSymbolLiteral): PropertyName;

/**
 * Interface for well-known symbol literal expressions
 */
interface WellKnownSymbolLiteral extends ts.PropertyAccessExpression {
  expression: ts.Identifier & {text: 'Symbol', escapedText: 'symbol'};
}

/**
 * Property name information
 */
interface PropertyName {
  displayName: string;
  symbolName: ts.__String;
}

Late-Bound Property Analysis

Utilities for analyzing dynamically computed property names.

/**
 * Analyze late-bound property names from an expression
 * @param node - Expression to analyze
 * @param checker - Type checker instance
 * @returns Late-bound property names information
 */
function getLateBoundPropertyNames(node: ts.Expression, checker: ts.TypeChecker): LateBoundPropertyNames;

/**
 * Get late-bound property names from a property name node
 * @param node - Property name node
 * @param checker - Type checker instance
 * @returns Late-bound property names information
 */
function getLateBoundPropertyNamesOfPropertyName(node: ts.PropertyName, checker: ts.TypeChecker): LateBoundPropertyNames;

/**
 * Get single late-bound property name if deterministic
 * @param node - Property name node
 * @param checker - Type checker instance
 * @returns Single property name if deterministic, undefined otherwise
 */
function getSingleLateBoundPropertyNameOfPropertyName(node: ts.PropertyName, checker: ts.TypeChecker): PropertyName | undefined;

/**
 * Late-bound property names result
 */
interface LateBoundPropertyNames {
  /** Whether all property names are known at compile time */
  known: boolean;
  /** Array of resolved property names */
  names: PropertyName[];
}

Expression Analysis

Utilities for analyzing expressions and their side effects.

/**
 * Check if expression has side effects
 * @param node - Expression to analyze
 * @param options - Side effect analysis options
 * @returns true if expression may have side effects
 */
function hasSideEffects(node: ts.Expression, options?: SideEffectOptions): boolean;

/**
 * Check if expression value is used (not discarded)
 * @param node - Expression to check
 * @returns true if expression value is used
 */
function isExpressionValueUsed(node: ts.Expression): boolean;

/**
 * Get access kind for a node (read, write, delete)
 * @param node - Node to analyze
 * @returns Access kind flags
 */
function getAccessKind(node: ts.Node): AccessKind;

/**
 * Check if expression is a reassignment target
 * @param node - Expression to check
 * @returns true if expression is being reassigned
 */
function isReassignmentTarget(node: ts.Expression): boolean;

/**
 * Side effect analysis options
 */
enum SideEffectOptions {
  None = 0,
  TaggedTemplate = 1,
  Constructor = 2,
  JsxElement = 4
}

/**
 * Access kind enumeration
 */
enum AccessKind {
  None = 0,
  Read = 1,
  Write = 2,
  Delete = 4,
  ReadWrite = Read | Write,
  Modification = Write | Delete
}

Const Assertion Analysis

Utilities for analyzing const assertions and readonly contexts.

/**
 * Check if assertion expression is a const assertion
 * @param node - Assertion expression to check
 * @returns true if assertion is 'as const'
 */
function isConstAssertion(node: ts.AssertionExpression): boolean;

/**
 * Check if expression is in const context
 * @param node - Expression to check
 * @returns true if expression is in const assertion context
 */
function isInConstContext(node: ts.Expression): boolean;

/**
 * Check if call expression is readonly assignment declaration
 * @param node - Call expression to check
 * @param checker - Type checker instance
 * @returns true if call creates readonly assignment
 */
function isReadonlyAssignmentDeclaration(node: ts.CallExpression, checker: ts.TypeChecker): boolean;

/**
 * Check if call expression is bindable Object.defineProperty call
 * @param node - Call expression to check
 * @returns true if call is bindable defineProperty
 */
function isBindableObjectDefinePropertyCall(node: ts.CallExpression): boolean;

Utility Functions

Miscellaneous text processing and utility functions.

/**
 * Remove parentheses from expression
 * @param node - Expression that may be parenthesized
 * @returns Unwrapped expression
 */
function unwrapParentheses(node: ts.Expression): ts.Expression;

/**
 * Format pseudo big int value as string
 * @param v - Pseudo big int value
 * @returns Formatted string representation
 */
function formatPseudoBigInt(v: ts.PseudoBigInt): string;

/**
 * Check if switch statement has exhaustive case clauses
 * @param node - Switch statement to check
 * @param checker - Type checker instance
 * @returns true if all cases are covered
 */
function hasExhaustiveCaseClauses(node: ts.SwitchStatement, checker: ts.TypeChecker): boolean;

/**
 * Get base class expression from class-like declaration
 * @param node - Class-like declaration
 * @returns Base class expression if present
 */
function getBaseOfClassLikeExpression(node: ts.ClassLikeDeclaration): ts.ExpressionWithTypeArguments | undefined;

Directive Analysis

Utilities for analyzing TypeScript compiler directives.

/**
 * Get TypeScript check directive from source text
 * @param source - Source text to analyze
 * @returns Check directive if found
 */
function getTsCheckDirective(source: string): ts.CheckJsDirective | undefined;

/**
 * Get check JS directive from source text (deprecated)
 * @param source - Source text to analyze
 * @returns Check directive if found
 * @deprecated Use getTsCheckDirective instead
 */
function getCheckJsDirective(source: string): ts.CheckJsDirective | undefined;

Usage Examples:

import * as ts from "typescript";
import { 
  getLineRanges, 
  isValidIdentifier, 
  getPropertyName,
  hasSideEffects,
  isConstAssertion,
  unwrapParentheses,
  SideEffectOptions,
  AccessKind
} from "tsutils/util";

// Line analysis example
function analyzeSourceLines(sourceFile: ts.SourceFile) {
  const lines = getLineRanges(sourceFile);
  const lineBreakStyle = getLineBreakStyle(sourceFile);
  
  console.log(`File has ${lines.length} lines`);
  console.log(`Line break style: ${JSON.stringify(lineBreakStyle)}`);
  
  lines.forEach((line, index) => {
    console.log(`Line ${index + 1}: ${line.contentLength} characters`);
  });
}

// Identifier validation example
function validateIdentifiers(identifiers: string[]) {
  identifiers.forEach(id => {
    if (isValidIdentifier(id)) {
      console.log(`"${id}" is a valid identifier`);
    } else {
      console.log(`"${id}" is not a valid identifier`);
    }
    
    if (isValidPropertyAccess(id)) {
      console.log(`"${id}" can be used in property access`);
    }
  });
}

// Property name analysis
function analyzePropertyAccess(node: ts.PropertyAccessExpression) {
  const propertyName = getPropertyName(node.name);
  if (propertyName) {
    console.log(`Property name: ${propertyName}`);
    
    if (isNumericPropertyName(propertyName)) {
      console.log("Property name is numeric");
    }
  }
}

// Side effect analysis
function analyzeSideEffects(expression: ts.Expression) {
  const hasEffects = hasSideEffects(expression, SideEffectOptions.None);
  const hasEffectsWithConstructors = hasSideEffects(expression, SideEffectOptions.Constructor);
  
  console.log(`Expression has side effects: ${hasEffects}`);
  console.log(`With constructor calls: ${hasEffectsWithConstructors}`);
  
  const isUsed = isExpressionValueUsed(expression);
  console.log(`Expression value is used: ${isUsed}`);
}

// Const assertion analysis
function analyzeConstAssertions(node: ts.Node) {
  if (ts.isAsExpression(node) || ts.isTypeAssertion(node)) {
    if (isConstAssertion(node)) {
      console.log("Found const assertion");
    }
  }
  
  if (ts.isExpression(node) && isInConstContext(node)) {
    console.log("Expression is in const context");
  }
}

// Expression unwrapping
function analyzeExpression(expr: ts.Expression) {
  const unwrapped = unwrapParentheses(expr);
  
  if (unwrapped !== expr) {
    console.log("Expression was parenthesized");
  }
  
  console.log(`Unwrapped expression: ${ts.SyntaxKind[unwrapped.kind]}`);
}

// Position-based analysis
function checkPositionInLine(sourceFile: ts.SourceFile, pos1: number, pos2: number) {
  if (isSameLine(sourceFile, pos1, pos2)) {
    console.log("Positions are on the same line");
  } else {
    console.log("Positions are on different lines");
  }
}

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