A Babel plugin that transforms TypeScript code into ES.next JavaScript by stripping TypeScript-specific syntax including type annotations, interfaces, enums, and other TypeScript constructs while preserving runtime behavior.
npm install --save-dev @babel/plugin-transform-typescriptThis plugin is not imported directly in code. Instead, it's configured in Babel configuration files:
Babel Config (.babelrc.json):
{
"plugins": ["@babel/plugin-transform-typescript"]
}Babel Config (babel.config.js):
module.exports = {
plugins: ["@babel/plugin-transform-typescript"]
};Programmatic Usage:
import babel from "@babel/core";
import transformTypeScript from "@babel/plugin-transform-typescript";
const result = babel.transformSync(code, {
plugins: [transformTypeScript]
});The plugin automatically transforms TypeScript syntax when processing files through Babel:
Input TypeScript:
interface User {
name: string;
age: number;
isActive?: boolean;
}
class UserManager {
private users: User[] = [];
addUser(user: User): void {
this.users.push(user);
}
getActiveUsers(): User[] {
return this.users.filter(u => u.isActive);
}
}
enum Status {
Active = "active",
Inactive = "inactive"
}Output JavaScript:
class UserManager {
constructor() {
this.users = [];
}
addUser(user) {
this.users.push(user);
}
getActiveUsers() {
return this.users.filter(u => u.isActive);
}
}
var Status = function(Status) {
Status["Active"] = "active";
Status["Inactive"] = "inactive";
return Status;
}({});The plugin operates as a Babel transform that:
Configure the plugin behavior through options passed to Babel.
interface Options {
/** Allow namespace declarations (default: true) */
allowNamespaces?: boolean;
/** JSX pragma function (default: "React.createElement") */
jsxPragma?: string;
/** JSX fragment pragma (default: "React.Fragment") */
jsxPragmaFrag?: string;
/** Only remove type-only imports/exports (default: false) */
onlyRemoveTypeImports?: boolean;
/** Optimize const enums by inlining values (default: false) */
optimizeConstEnums?: boolean;
/** Allow declare field modifiers (default: false, Babel 7 only - removed in Babel 8) */
allowDeclareFields?: boolean;
// Inherited from @babel/plugin-syntax-typescript:
/** Disallow ambiguous JSX-like expressions (default: false) */
disallowAmbiguousJSXLike?: boolean;
/** Process .d.ts declaration files (default: false) */
dts?: boolean;
/** Enable TSX (JSX in TypeScript) parsing (default: false) */
isTSX?: boolean;
}Usage with Options:
{
"plugins": [
["@babel/plugin-transform-typescript", {
"allowNamespaces": false,
"onlyRemoveTypeImports": true,
"optimizeConstEnums": true
}]
]
}Removes TypeScript type annotations while preserving runtime behavior.
Transformations handled:
value as Type becomes valuevalue! becomes valueTransforms TypeScript enums to JavaScript objects with proper value assignment, including advanced features like enum merging and cross-references.
Regular Enums:
// Input
enum Direction {
Up,
Down,
Left = "left",
Right = "right"
}
// Output
var Direction = function(Direction) {
Direction[Direction["Up"] = 0] = "Up";
Direction[Direction["Down"] = 1] = "Down";
Direction["Left"] = "left";
Direction["Right"] = "right";
return Direction;
}({});Const Enums (with optimizeConstEnums: true):
// Input
const enum Status {
Loading = "loading",
Success = "success"
}
console.log(Status.Loading);
// Output
console.log("loading");Enum Cross-References and Mathematical Operations:
// Input
enum Values {
A = 1,
B = A * 2,
C = B + A,
D = Math.floor(3.14)
}
// Output
var Values = function(Values) {
Values[Values["A"] = 1] = "A";
Values[Values["B"] = 2] = "B";
Values[Values["C"] = 3] = "C";
Values[Values["D"] = 3] = "D";
return Values;
}({});Enum Declaration Merging:
// Input
enum Color { Red, Green }
enum Color { Blue = 2 }
// Output - Merges into single enum object
var Color = function(Color) {
Color[Color["Red"] = 0] = "Red";
Color[Color["Green"] = 1] = "Green";
Color[Color["Blue"] = 2] = "Blue";
return Color;
}({});Transforms TypeScript namespace declarations to JavaScript patterns when allowNamespaces is enabled, including support for qualified names and strict export restrictions.
Basic Namespace:
// Input
namespace Utils {
export function helper() { return "help"; }
export const VERSION = "1.0";
}
// Output
var Utils = function() {
function helper() { return "help"; }
const VERSION = "1.0";
return { helper, VERSION };
}();Qualified Namespace Names:
// Input
namespace A.B.C {
export const value = 42;
}
// Output
var A = A || {};
A.B = A.B || {};
A.B.C = function() {
const value = 42;
return { value };
}();Namespace Export Restrictions:
Namespaces can only export const declarations, functions, classes, and other namespaces. Non-const variable exports will cause compilation errors:
// This will fail:
namespace Utils {
export let mutableValue = 1; // Error: only const exports allowed
}
// This works:
namespace Utils {
export const immutableValue = 1; // OK
export function doSomething() {} // OK
}Removes type-only imports and exports while preserving value imports.
Type Import Removal:
// Input
import type { User } from './types';
import { UserService, type Config } from './service';
// Output
import { UserService } from './service';Export Handling:
// Input
export type { User };
export { UserService, type Config };
// Output
export { UserService };Handles TypeScript class features while preserving JavaScript class behavior.
Parameter Properties:
// Input
class User {
constructor(
public name: string,
private age: number,
readonly id: string
) {}
}
// Output
class User {
constructor(name, age, id) {
this.name = name;
this.age = age;
this.id = id;
}
}Parameter Property Restrictions: Parameter properties cannot use destructuring patterns:
// This will fail:
class User {
constructor(
public { name, age }: UserData, // Error: destructuring not allowed
private options?: { debug: boolean }
) {}
}
// Error: "Parameter properties can not be destructuring patterns"Field Declarations:
// Input
class Service {
private cache?: Map<string, any>;
public readonly version: string = "1.0";
declare ready: boolean;
}
// Output
class Service {
constructor() {
this.version = "1.0";
}
}Handles TypeScript-specific JSX features while preserving React JSX transformation.
Generic JSX:
// Input
const element = <Component<string> value="test" />;
// Output
const element = React.createElement(Component, { value: "test" });Type Arguments Removal:
// Input
createElement<Props>(Component, props);
// Output
createElement(Component, props);Supports CommonJS export assignment transformation when CommonJS modules are enabled.
// Input (TypeScript module syntax)
export = myFunction;
// Output (CommonJS)
module.exports = myFunction;The plugin throws compilation errors for unsupported patterns with specific error messages:
Namespace errors (when allowNamespaces: false):
// Error message when namespaces are disabled but used
"Namespaces are not supported when allowNamespaces is false"Declare fields without allowDeclareFields (Babel 7 only):
// Error message when using declare without enabling the option
"The 'declare' modifier is only allowed when the 'allowDeclareFields' option of @babel/plugin-transform-typescript or @babel/preset-typescript is enabled"Parameter property destructuring:
// This will fail:
class User {
constructor(
public { name, age }: UserData // Error: destructuring not allowed
) {}
}
// Error: "Parameter properties can not be destructuring patterns"Declare fields with initializers:
// This will fail:
class Service {
declare initialized: boolean = true; // Error: declare fields cannot have initializers
}
// Error: "Fields with the 'declare' modifier cannot be initialized here, but only in the constructor"Definitely assigned fields with initializers:
// This will fail:
class Service {
ready!: boolean = false; // Error: definite assignment with initializer
}
// Error: "Definitely assigned fields cannot be initialized here, but only in the constructor"Export assignment without CommonJS transform:
// This will fail without @babel/plugin-transform-modules-commonjs:
export = myFunction;
// Error: "`export = <value>;` is only supported when compiling modules to CommonJS. Please consider using `export default <value>;`, or add @babel/plugin-transform-modules-commonjs to your Babel config"Import equals without CommonJS transform:
// This will fail without CommonJS transform:
import foo = require('./bar');
// Error: "`import foo = require(...);` is only supported when compiling modules to CommonJS. Please consider using `import foo from '...';` alongside TypeScript's --allowSyntheticDefaultImports option"Non-const variable exports in namespaces:
// This will fail:
namespace Utils {
export let mutable = 1; // Error: only const exports allowed
}
// Error: "Namespaces exporting non-const are not supported by Babel. Change to const or see: https://babeljs.io/docs/en/babel-plugin-transform-typescript"Nested ambient modules:
// This will fail:
declare module "outer" {
declare module "inner" {} // Error: nested ambient modules not supported
}Enum member without initializer after string member:
// This will fail:
enum Mixed {
A = "string",
B // Error: must have initializer after string member
}
// Error: "Enum member must have initializer"The plugin behavior differs between Babel 7 and Babel 8:
allowDeclareFields option: Available in Babel 7 to control handling of declare field modifiers!) are removed when allowDeclareFields: falseimport foo = require() syntax with isExport propertyallowDeclareFields removed: The allowDeclareFields option is not available in Babel 8superTypeParameters → superTypeArguments)When upgrading from Babel 7 to Babel 8:
allowDeclareFields option from configurationdeclare or definite assignment (!)With TypeScript Preset:
{
"presets": [
["@babel/preset-typescript", {
"allowNamespaces": true,
"onlyRemoveTypeImports": false
}]
]
}Standalone Plugin Usage:
{
"plugins": [
"@babel/plugin-syntax-typescript",
["@babel/plugin-transform-typescript", {
"allowNamespaces": false
}]
]
}The plugin requires @babel/plugin-syntax-typescript for parsing TypeScript syntax and automatically inherits from it when used.