# How BiomeJS Handles TypeScript: Parsing, Analysis, and Semantic Integration

> Discover how BiomeJS handles TypeScript. Learn about its parsing, analysis, and semantic integration strategies for efficient code processing.

- Repository: [Biome/biome](https://github.com/biomejs/biome)
- Tags: internals
- Published: 2026-06-19

---

**BiomeJS handles TypeScript by detecting the source type, activating the `TypeScript` feature flag, and routing exclusive syntax through gated parsing functions while maintaining context via the `TypeContext` struct.**

BiomeJS treats TypeScript as an optional language extension of its core JavaScript parser. When parsing files in the `biomejs/biome` repository, the parser checks the source type and enables TypeScript-specific grammar rules, allowing the same `JsParser` infrastructure to handle both JavaScript and TypeScript seamlessly.

## Language Detection via Feature Flags

The parser determines whether a file contains TypeScript by checking the `JsSyntaxFeature::TypeScript` flag. In [`crates/biome_js_parser/src/lib.rs`](https://github.com/biomejs/biome/blob/main/crates/biome_js_parser/src/lib.rs), the `is_supported` method evaluates whether the source type's language is TypeScript:

```rust
// biome_js_parser/src/lib.rs
pub enum JsSyntaxFeature {
    TypeScript,
    // …
}

impl SyntaxFeature for JsSyntaxFeature {
    fn is_supported(&self, p: &JsParser) -> bool {
        match self {
            Self::TypeScript => p.source_type().language().is_typescript(),
            // …
        }
    }
}

```

When `is_supported` returns true, the parser unlocks TypeScript-exclusive syntax paths. This check occurs at lines 90–106 in [`lib.rs`](https://github.com/biomejs/biome/blob/main/lib.rs), ensuring that TypeScript constructs are only parsed when the input file is explicitly identified as TypeScript or TSX.

## Gating TypeScript-Exclusive Syntax

Rather than branching the entire parser, BiomeJS uses exclusive syntax gates to handle TypeScript-specific productions. The `parse_exclusive_syntax` method wraps TypeScript-only functions and validates the feature flag before execution. In [`crates/biome_js_parser/src/syntax/stmt.rs`](https://github.com/biomejs/biome/blob/main/crates/biome_js_parser/src/syntax/stmt.rs), the statement parser invokes this gate for constructs like enums:

```rust
// biome_js_parser/src/syntax/stmt.rs
TypeScript.parse_exclusive_syntax(p, parse_ts_enum_declaration, |p, decl| { … });

```

This pattern appears at line 206. If the `TypeScript` feature is not enabled, the parser skips the TypeScript-specific logic and falls back to standard JavaScript rules, emitting diagnostics for unsupported constructs.

## Modular TypeScript Grammar

The TypeScript grammar implementation resides in `crates/biome_js_parser/src/syntax/typescript/`. This directory contains specialized modules that extend the core JavaScript parser:

- **[`types.rs`](https://github.com/biomejs/biome/blob/main/types.rs)** – Handles type annotations, unions, intersections, and type literals
- **[`statement.rs`](https://github.com/biomejs/biome/blob/main/statement.rs)** – Parses TypeScript-specific statements including `enum`, `interface`, and `declare` modifiers
- **[`module.rs`](https://github.com/biomejs/biome/blob/main/module.rs)** – Processes module-level syntax such as `import =`, `export =`, and `namespace` declarations
- **[`ts_parse_error.rs`](https://github.com/biomejs/biome/blob/main/ts_parse_error.rs)** – Generates custom error messages for TypeScript-only constructs

The header of [`types.rs`](https://github.com/biomejs/biome/blob/main/types.rs) (lines 1–27) defines the imports and module structure for type parsing.

### TypeContext for Advanced Constructs

Parsing complex TypeScript features requires contextual awareness. The `TypeContext` struct in [`crates/biome_js_parser/src/syntax/typescript/types.rs`](https://github.com/biomejs/biome/blob/main/crates/biome_js_parser/src/syntax/typescript/types.rs) tracks parsing flags such as conditional type allowance and `in/out` modifier support:

```rust
// biome_js_parser/src/syntax/typescript/types.rs
#[derive(Debug, Default, Copy, Clone)]
pub(crate) struct TypeContext(BitFlags<ContextFlag>);

```

Defined between lines 48–88, this struct provides methods like `and_allow_in_out_modifier` to toggle capabilities while descending the AST. These context flags ensure that modifiers like `in` and `out` are only permitted in valid locations, such as within type parameter declarations.

## Error Handling for TypeScript Constructs

When TypeScript syntax appears in JavaScript files, or when invalid constructs are encountered, the parser generates specific diagnostics via [`ts_parse_error.rs`](https://github.com/biomejs/biome/blob/main/ts_parse_error.rs). For example, attempting to use a `declare` modifier in a standard JavaScript file triggers an error at the parsing stage. In [`crates/biome_js_parser/src/syntax/stmt.rs`](https://github.com/biomejs/biome/blob/main/crates/biome_js_parser/src/syntax/stmt.rs) (line 357), the error is constructed as follows:

```rust
// biome_js_parser/src/syntax/stmt.rs
TypeScript.parse_exclusive_syntax(p, parse_ts_declare_statement, |p, _| {
    p.err_builder("The `declare` modifier can only be used in TypeScript files.", range)
});

```

This ensures clear, actionable error messages that distinguish between JavaScript and TypeScript parsing modes.

## Semantic Analysis and Type Resolution

After parsing, the TypeScript AST nodes flow into the semantic analyzer (`biome_js_semantic`). This component resolves type references, handles declaration merging, and provides type information to LSP features. The `biome_js_type_info` crate contains utilities for type data management, including declaration merging logic in [`type_data.rs`](https://github.com/biomejs/biome/blob/main/type_data.rs) (line 123) and local inference capabilities in [`local_inference.rs`](https://github.com/biomejs/biome/blob/main/local_inference.rs).

The semantic layer transforms the parsed syntax tree into a fully resolved representation, enabling BiomeJS to perform type-aware linting and provide accurate IDE support for TypeScript projects.

## End-to-End TypeScript Parsing Example

To parse a TypeScript file programmatically, instantiate the parser with a TypeScript source type:

```rust
use biome_js_parser::{JsParser, JsParserOptions};
use biome_js_parser::source_type::SourceType;

fn parse_ts(source: &str) -> biome_js_syntax::JsSyntaxNode {
    // Declare that the source is TypeScript
    let source_type = SourceType::tsx(); // or .ts() for plain TS
    
    // Build parser options with the source type
    let options = JsParserOptions::default().with_source_type(source_type);
    
    // Create the parser
    let mut parser = JsParser::new(source, options);
    
    // Parse the program (top-level)
    let root = parser.parse_program();
    
    // Retrieve the syntax tree
    root.syntax()
}

```

Calling `SourceType::tsx()` marks the input as TypeScript JSX, enabling the `TypeScript` feature flag. The parser automatically routes all TypeScript constructs through the exclusive-syntax gates, constructing AST nodes with `SyntaxKind` variants like `TS_TYPE_ANNOTATION`.

## Summary

- **Feature Flag Detection**: BiomeJS detects TypeScript files via `JsSyntaxFeature::TypeScript.is_supported()` in [`crates/biome_js_parser/src/lib.rs`](https://github.com/biomejs/biome/blob/main/crates/biome_js_parser/src/lib.rs), which checks if the source type language is TypeScript.
- **Exclusive Syntax Gates**: TypeScript-specific constructs are parsed through `parse_exclusive_syntax()` methods that validate the feature flag before executing TypeScript logic.
- **Modular Grammar**: TypeScript parsing is organized into dedicated modules under `syntax/typescript/`, including [`types.rs`](https://github.com/biomejs/biome/blob/main/types.rs) for type annotations and [`ts_parse_error.rs`](https://github.com/biomejs/biome/blob/main/ts_parse_error.rs) for diagnostics.
- **Context Tracking**: The `TypeContext` struct manages parsing states for advanced features like conditional types and variance modifiers.
- **Semantic Integration**: The `biome_js_semantic` crate and `biome_js_type_info` handle type resolution and declaration merging after parsing.

## Frequently Asked Questions

### How does BiomeJS detect if a file is TypeScript?

BiomeJS detects TypeScript files by examining the source type using `p.source_type().language().is_typescript()` within the `is_supported` method of `JsSyntaxFeature`. This check occurs in [`crates/biome_js_parser/src/lib.rs`](https://github.com/biomejs/biome/blob/main/crates/biome_js_parser/src/lib.rs) and returns true for `.ts` and `.tsx` extensions, enabling the TypeScript feature flag for that parse session.

### What happens when TypeScript syntax is used in a JavaScript file?

When TypeScript-specific syntax like `declare` or `interface` appears in a JavaScript file, the parser encounters an exclusive syntax gate that checks the `TypeScript` feature flag. Since the flag is disabled for JavaScript files, the parser emits a diagnostic error—such as "The `declare` modifier can only be used in TypeScript files"—and falls back to standard JavaScript parsing rules.

### How does BiomeJS handle complex TypeScript features like conditional types?

Complex features are managed via the `TypeContext` struct in [`crates/biome_js_parser/src/syntax/typescript/types.rs`](https://github.com/biomejs/biome/blob/main/crates/biome_js_parser/src/syntax/typescript/types.rs). This struct maintains bit flags for contextual permissions, such as allowing conditional types or `in/out` modifiers. As the parser descends into the AST, it creates modified contexts using methods like `and_allow_in_out_modifier()` to ensure syntax validity at specific tree depths.

### Where does BiomeJS store type information after parsing?

Type information is processed by the `biome_js_semantic` crate after the initial parse. Declaration merging and type data structures are defined in [`crates/biome_js_type_info/src/type_data.rs`](https://github.com/biomejs/biome/blob/main/crates/biome_js_type_info/src/type_data.rs), while local type inference logic resides in [`local_inference.rs`](https://github.com/biomejs/biome/blob/main/local_inference.rs). These modules provide the resolved type information used by BiomeJS's linting rules and LSP features.