@itrocks/ast
v0.3.0
Published
Parses TypeScript source into a parser-agnostic abstract syntax tree
Maintainers
Readme
ast
Parses TypeScript source into a parser-agnostic abstract syntax tree.
The returned model covers imports, classes, interfaces, type aliases, decorators, class members, common expressions, and common TypeScript types. It contains only plain JavaScript objects and never exposes parser-native nodes.
Requirements
- Node.js 24 or later.
- One supported optional parser dependency. TypeScript 6.0.x, TypeScript 7.0.x, and oxc-parser 0.144.x are currently supported.
Installation
npm i @itrocks/astThe typescript and oxc-parser packages are optional. npm installs optional
dependencies by default. If you omit them, install at least one supported parser
explicitly before calling parse.
Usage
Pass source text directly to parse. The package does not read files itself.
import { parse } from '@itrocks/ast'
const module = parse(`
import { Identifier as Id } from './identifier.js'
@Entity('users')
export class User {
id?: Id
name = 'Anonymous'
}
`, 'user.ts')
console.log(module.imports[0])
// {
// from: './identifier.js',
// default: undefined,
// named: [{ imported: 'Identifier', local: 'Id' }]
// }
console.log(module.declarations[0])
// {
// kind: 'class',
// name: 'User',
// exported: true,
// isDefault: false,
// decorators: [{
// name: 'Entity',
// arguments: [{ kind: 'literal', value: 'users' }]
// }],
// members: [
// {
// kind: 'property',
// name: 'id',
// optional: true,
// type: { kind: 'reference', name: 'Id', arguments: [] },
// initializer: undefined
// },
// {
// kind: 'property',
// name: 'name',
// optional: false,
// type: undefined,
// initializer: { kind: 'literal', value: 'Anonymous' }
// }
// ]
// }Behaviour
- Parsing is synchronous.
autois selected by default. It chooses the first installed supported parser, preferring TypeScript and falling back to oxc-parser.- The
typescriptparser automatically selects its 6.0.x or 7.0.x implementation from the installedtypescriptversion. - The
oxcparser explicitly selects the installed oxc-parser implementation. - Imports, declarations, members, parameters, decorator arguments, and composite types retain source order.
parsereturns only top-level class, interface, and type alias declarations.parseAllalso finds these declarations inside namespaces and other nested scopes.- Unsupported expressions and types use
{ kind: 'unknown', raw }instead of exposing a native parser node. - Invalid TypeScript syntax throws an
Error. - Parser selection is global to the current process and affects subsequent calls.
The model is intentionally syntactic. It does not resolve modules, symbols, aliases, or global types, and it does not evaluate expressions.
API
parse
function parse(source: string, fileName?: string): ModuleParses TypeScript source and returns its normalized imports and top-level declarations.
Parameters:
source: TypeScript source text. No filesystem access is performed.fileName: Name associated with the source. It controls syntax recognition for names such asmodel.d.tsand is returned asModule.fileName. Defaults tosource.ts.
Returns:
A Module containing plain JavaScript objects.
parseAll
function parseAll(source: string, fileName?: string): ModuleParses TypeScript source like parse, but recursively collects class,
interface, and type alias declarations from nested scopes as well as the module scope.
Use this when declarations inside namespaces or similar containers must be discoverable. Imports remain the module's top-level imports.
useParser
type ParserName = 'auto' | 'oxc' | 'typescript'
function useParser(name: ParserName): voidSelects the parser used by subsequent calls to parse and parseAll. auto searches
installed parser dependencies in priority order; typescript requires that specific
parser and selects the implementation matching its installed version; oxc requires
oxc-parser.
Call this once during application startup, before parsing source. The selection is global
to the process. JavaScript callers passing an unavailable parser name receive a
RangeError.
import { useParser } from '@itrocks/ast'
useParser('typescript')
// or
useParser('oxc')Development and tests
npm run build
npm testThe build first installs the development and optional parser dependencies locally,
without running dependency lifecycle scripts or creating a package lock, then compiles
with the installed TypeScript version. npm test runs that build automatically before
compiling the complete source with both the latest configured TypeScript 6.x compiler
and TypeScript 7.x and running the shared parser contract against TypeScript 6,
TypeScript 7, and oxc-parser.
AST model
Every node is a discriminated plain object. Check kind to narrow declaration, member,
expression, and type unions.
Module and imports
type Module = {
fileName: string
imports: ImportDeclaration[]
declarations: Declaration[]
}
type ImportDeclaration = {
from: string
default?: string
named: ImportSpecifier[]
}
type ImportSpecifier = {
imported: string
local: string
}imported is the exported name in the source module. local is the name used by the
parsed module, so import { User as Account } produces
{ imported: 'User', local: 'Account' }.
Declarations
type Declaration = ClassDeclaration | InterfaceDeclaration | TypeAliasDeclaration
type ClassDeclaration = {
kind: 'class'
name?: string
exported: boolean
isDefault: boolean
decorators: Decorator[]
members: ClassMember[]
}
type InterfaceDeclaration = {
kind: 'interface'
name: string
exported: boolean
}
type TypeAliasDeclaration = {
kind: 'type-alias'
name: string
exported: boolean
type: TypeNode
}Anonymous default classes have no name. Declarations that are not part of this union,
such as functions, enums, variables, and namespaces themselves, are not returned.
Class members and decorators
type ClassMember = ConstructorDeclaration | MethodDeclaration | PropertyDeclaration
type ConstructorDeclaration = {
kind: 'constructor'
parameters: Parameter[]
}
type MethodDeclaration = {
kind: 'method'
name?: string
parameters: Parameter[]
}
type PropertyDeclaration = {
kind: 'property'
name?: string
optional: boolean
type?: TypeNode
initializer?: Expression
}
type Parameter = {
name?: string
}
type Decorator = {
name?: string
arguments: Expression[]
}Names are present for identifiers and simple string or numeric property names.
Computed names and destructured parameters have no name. Decorator names are present
for simple decorators such as @Route('/users'); qualified or computed decorators may
have no name.
Expressions
type LiteralValue = boolean | number | null | string
type Expression =
| { kind: 'literal', value: LiteralValue }
| { kind: 'identifier', name: string }
| { kind: 'array', elements: Expression[] }
| { kind: 'object', properties: ObjectProperty[] }
| { kind: 'unknown', raw: string }
type ObjectProperty = {
name?: string
value: Expression
}String literals and templates without substitutions both become string literals.
Calls, new expressions, spreads, templates with substitutions, and other unsupported
syntax become unknown. The parser never executes an expression.
TypeScript types
type PrimitiveTypeName = 'bigint' | 'boolean' | 'number' | 'object' | 'string' | 'symbol'
type TypeNode =
| { kind: 'primitive', name: PrimitiveTypeName }
| { kind: 'literal', value: LiteralValue | undefined }
| { kind: 'array', element: TypeNode }
| { kind: 'intersection', types: TypeNode[] }
| { kind: 'union', types: TypeNode[] }
| { kind: 'reference', name: string, arguments: TypeNode[] }
| { kind: 'unknown', raw: string }Reference names preserve their syntax, including qualified names such as
Domain.User. References and aliases are not resolved. Unsupported syntax retains its
source text in raw.
Limitations
This package provides parsing and normalization only. It does not:
- read or locate
.tsand.d.tsfiles; - cache source text or parsed modules;
- resolve imports, symbols, aliases, or types;
- expose source positions, comments, or parser-specific diagnostics;
- modify, print, or generate TypeScript source.
Packages that transform compiler nodes must continue to use a compiler transformation API for that part of their work.
