JavaScript API

Ast

An AST with its source text, optional language metadata and source map, and mutable program access.

Ast carries an ESTree Program, the source text its spans anchor to, optional language metadata, and an optional incremental source map. Every AST-bearing hook receives an Ast.

type AstOptions = {
    program: Program;
    source: string;
    language?: Language;
    map?: SourceMap;
};

class Ast {
    constructor(options: AstOptions);

    get program(): DeepReadonly<Program>;
    get source(): Readonly<string>;
    get language(): Language | void;
    get sourceType(): SourceType;
    get map(): DeepReadonly<SourceMap> | null;

    mutate<Result extends void | Promise<void>>(
        fn: (program: Program) => Result,
    ): Result;
}

Constructor

FieldTypeDescription
programProgramThe ESTree program.
sourcestringThe source text the program's spans anchor to.
languageLanguageOptional grammar of the program. Omit for new Ast({ program, source }): ESTree cannot carry grammar, so it stays undefined.
mapSourceMapOptional incremental source map. Omit when unavailable.

Members

MemberTypeDescription
programDeepReadonly<Program>A deeply read-only view of the program. Use mutate to change it.
sourcestringThe source text the program's spans anchor to.
languageLanguage | voidThe grammar of the program, or undefined when unknown. Populated by parse, rewrite, and createParser.
sourceTypeSourceTypeThe module kind, read through from program.sourceType. Values are "script" | "module" | "commonjs".
mapDeepReadonly<SourceMap> | nullThe incremental source map, or null when the AST carries none.
mutate(fn) => ResultRuns fn with mutable access to the program and returns its result.

sourceType is a read-through of ast.program.sourceType; it never returns "unambiguous". There is no stored source-type field, so changes made through Ast.mutate are reflected immediately.

When an entry point resolves a grammar, explicit options.language wins over Ast.language, which wins over the file extension.

The program getter is typed as DeepReadonly<Program>, so nested nodes and arrays cannot be changed through it.

mutate returns void for a synchronous callback and Promise<void> for an asynchronous one. The returned value matches the callback, so await ast.mutate(fn) works in both cases.

Mutation

Only the transform hook carries mutations forward: mutate args.ast and return { ast: args.ast } to replace the compiler's AST for the rest of the chain. Returning nothing discards the mutation.

The prepare, finalize, and generate hooks receive a snapshot of the compiler's AST. Mutating that snapshot changes only the local instance and does not alter the compiler's AST. A generate hook can pass a mutated AST to createGenerator to generate from it.

Example

import type { AstResult } from "telarel";

import { parse } from "telarel";

const { ast }: AstResult = await parse("const x: number = 1;");

ast.mutate((program): void => {
    program.body.length = 0;
});

Last updated on

Copyright © 2026, Alpheus

On this page