Babel TypeScript Preset
`@babel/preset-typescript` is a Babel preset specifically designed to strip TypeScript syntax from source code, converting it into standard JavaScript. It does not perform any type checking; its sole purpose is to remove type annotations, enums, and other TypeScript-specific constructs so that Babel can continue processing the resulting JavaScript. This allows developers to leverage Babel's extensive plugin ecosystem for further transformations, such as targeting older JavaScript environments with `@babel/preset-env` or integrating JSX transformations. The package is part of the Babel monorepo, maintaining an active release schedule with frequent patch and minor updates (often bi-weekly) and new major versions released periodically. As of April 2026, the `7.x` series is stable, with `7.29.2` being a recent patch, while the `8.x` series is in a release candidate phase, with `8.0.0-rc.3` being the latest. Its primary differentiator is enabling a unified transformation pipeline for projects using TypeScript in conjunction with various Babel features that the TypeScript compiler alone does not provide.
Common errors
-
SyntaxError: Cannot find preset 'typescript' relative to file
cause The `@babel/preset-typescript` package is not installed or incorrectly referenced in your Babel configuration.fixRun `npm install --save-dev @babel/preset-typescript` or `yarn add --dev @babel/preset-typescript`. In your `.babelrc.json` or `babel.config.js`, ensure the preset is listed as `"@babel/preset-typescript"` or `['@babel/preset-typescript', {...}]`. -
SyntaxError: Private field '#myField' must be declared in an enclosing class
cause Babel presets like `babel-preset-typescript` handle specific syntax. Modern JavaScript features (like private class fields, optional chaining, nullish coalescing) require `babel-preset-env` or specific plugins.fixInstall `@babel/preset-env` (`npm install --save-dev @babel/preset-env`) and include it in your Babel configuration, typically after `babel-preset-typescript`. Example: `presets: [['@babel/preset-typescript'], ['@babel/preset-env', { targets: { node: 'current' }}]]`. -
ReferenceError: require is not defined in ES module scope
cause You are attempting to use `require()` in an ES module environment, potentially within a `babel.config.js` or another configuration file that is treated as ESM.fixIf your `babel.config.js` or similar file is in an ES module context, use `import` statements instead of `require()`. For Babel presets, this might look like `import presetTypescript from '@babel/preset-typescript'; export default { presets: [presetTypescript] };`.
Warnings
- gotcha Babel's TypeScript preset only strips type annotations; it does not perform type checking. This means your code will transpile even if it contains type errors.
- breaking Starting with Babel 8, support for the legacy TypeScript `module <identifier>` syntax (internal modules/namespaces) has been dropped.
- gotcha `@babel/preset-typescript` must typically be listed before `@babel/preset-env` (or other syntax-transforming presets) in your Babel configuration `presets` array.
Install
-
npm install babel-preset-typescript -
yarn add babel-preset-typescript -
pnpm add babel-preset-typescript
Imports
- typescript (in .babelrc.json)
{ "plugins": [ "@babel/preset-typescript" ] }{ "presets": [ "@babel/preset-typescript" ] } - @babel/preset-typescript (in babel.config.js)
// babel.config.js module.exports = { presets: [ '@babel/preset-typescript' // No array for options or just 'typescript' ] };// babel.config.js module.exports = { presets: [ ['@babel/preset-typescript', { // options for the preset is='value' }] ] }; - transformAsync (Node API)
const babel = require('babel-core'); // Deprecated package babel.transform(code, { presets: ['typescript'] });import * as babel from '@babel/core'; const code = `const x: number = 42;`; const result = await babel.transformAsync(code, { filename: 'input.ts', // Important for preset to recognize TS presets: [ ['@babel/preset-typescript', { allowDeclareFields: true }], ['@babel/preset-env', { targets: { node: 'current' } }] ] }); console.log(result?.code);
Quickstart
import * as babel from '@babel/core';
const typescriptCode = `
interface Shape {
area(): number;
}
class Circle implements Shape {
constructor(public radius: number) {}
area(): number {
return Math.PI * this.radius * this.radius;
}
}
const myCircle: Circle = new Circle(10);
console.log('Circle area:', myCircle.area());
const greeting: string = 'Hello Babel!';
console.log(greeting);
`;
async function transformTsCode() {
try {
const result = await babel.transformAsync(typescriptCode, {
filename: 'example.ts', // Essential for Babel to correctly apply TS preset
presets: [
['@babel/preset-typescript', {
// Example option: allows properties of classes to be declared without an initializer
allowDeclareFields: true
}],
['@babel/preset-env', {
// Transpile for the current Node.js version
targets: { node: 'current' }
}]
]
});
console.log('--- Original TypeScript Code ---\n', typescriptCode);
console.log('\n--- Transformed JavaScript Code (via Babel) ---\n', result?.code);
} catch (error) {
console.error('Babel transformation failed:', error);
}
}
transformTsCode();