Skip to content

About

Acorn plugin that parses TypeScript

Resources

Security policy

Stars

50 stars

Watchers

2 watching

Forks

Repository files navigation

@sveltejs/acorn-typescript

License Chat

This is a plugin for Acorn - a tiny, fast JavaScript parser, written completely in JavaScript.

It was created as an experimental alternative, faster TypeScript parser. It will help you to parse TypeScript using Acorn.

Usage

To get started, import the plugin and use Acorn's extension mechanism to register it. You have to enable options.locations while using @sveltejs/acorn-typescript.

import { Parser } from 'acorn';
import { tsPlugin } from '@sveltejs/acorn-typescript';

const node = Parser.extend(tsPlugin()).parse(
	`
const a = 1
type A = number
export {
  a,
  type A as B
}
`,
	{
		sourceType: 'module',
		ecmaVersion: 'latest',
		locations: true
	}
);

If you want to enable parsing within a TypeScript ambient context, where certain syntax have different rules (like .d.ts files and inside declare module blocks):

import { Parser } from 'acorn';
import { tsPlugin } from '@sveltejs/acorn-typescript';

const node = Parser.extend(tsPlugin({ dts: true })).parse(
	`
const a = 1
type A = number
export {
  a,
  type A as B
}
`,
	{
		sourceType: 'module',
		ecmaVersion: 'latest',
		locations: true
	}
);

Parser responsibilities

This plugin produces a syntax tree; successful parsing does not mean that a program passes TypeScript's type checker. Imports and local declarations can share a name, because an imported type and a local value live in separate declaration spaces. For example, this is valid TypeScript:

import type { A } from './a';
const A = 1;

This also applies to ordinary imports, not only type-only imports. The following is valid when Config is exported from ./types as a type only:

import { Config } from './types';
const Config = { path: '/' };

The parser does not know whether an imported name refers to a type or a value, so it also accepts the same code when Config is exported as a value, even though TypeScript's checker then reports Import declaration conflicts with local declaration of 'Config'.

Internal import aliases (import A = M) and type-only external aliases (import type A = require('a')) can also share a name with local declarations. Ordinary external aliases (import A = require('a')) still use lexical binding checks and cannot share a name with a const in the same scope. The parser does not resolve the imported symbol or decide whether an accepted combination is semantically valid. Use TypeScript's checker when your application needs those diagnostics.

An ordinary import and a type-only named import can also share a binding name. The parser still rejects malformed syntax and certain duplicate declarations in the same scope. For example, each of the following throws a parser error:

import { A } from './a';
import { A } from './b';
const A = 1;
const A = 2;
type A = number;
type A = string;

These examples describe the scope of the import/local-name checks, rather than a complete list of the parser's syntax and declaration checks.

SUPPORTED

  • Typescript normal syntax
  • Support to parse TypeScript Decorators
  • Support to parse JSX & TSX

CHANGELOG

click

Migration

Upgrading from v1? See the v1 to v2 migration guide, including the ImportExpression.options AST change and Acorn configuration requirements.

Acknowledgments

We want to thank TyrealHu for his original work on this project. He maintained acorn-typescript until early 2024.

About

Acorn plugin that parses TypeScript

Resources

Security policy

Stars

50 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages