@babel/plugin-transform-typescript
This plugin is included in
@babel/preset-typescript
This plugin adds support for the types syntax used by the TypeScript programming language . However, this plugin does not add the ability to type-check the JavaScript passed to it. For that, you will need to install and set up TypeScript.
Note that although the TypeScript compiler
tsc
actively supports certain JavaScript proposals such as optional chaining (
?.
), nullish coalescing (
??
) and class properties (
this.#x
), this preset does not include these features because they are not the types syntax available in TypeScript only. We recommend using
preset-env
with
preset-typescript
if you want to transpile these features.
Example
const x: number = 0;
const x = 0;
Installation
- npm
- Yarn
- pnpm
npm install --save-dev @babel/plugin-transform-typescript
yarn add --dev @babel/plugin-transform-typescript
pnpm add --save-dev @babel/plugin-transform-typescript
Usage
With a configuration file (Recommended)
{
"plugins": ["@babel/plugin-transform-typescript"]
}
Via CLI
babel --plugins @babel/plugin-transform-typescript script.js
Via Node API
require("@babel/core").transformSync("code", {
plugins: ["@babel/plugin-transform-typescript"],
});
Options
allowDeclareFields
boolean
, defaults to
false
Added in
v7.7.0
This will be enabled by default in Babel 8
When enabled, type-only class fields are only removed if they are prefixed with the
declare
modifier:
class A {
declare foo: string; // Removed
bar: string; // Initialized to undefined
}
allowNamespaces
boolean
, defaults to
true
.
History
Version | Changes |
---|---|
v7.5.0
|
Added
allowNamespaces
, defaults to
false
|
v7.13.0
|
defaults to
true
|
Enables compilation of TypeScript namespaces.
disallowAmbiguousJSXLike
boolean
, defaults to
false
Added in:
v7.16.0
Even when JSX parsing is not enabled, this option disallows using syntax that would be ambiguous with JSX (
<X> y
type assertions and
<X>() => {}
type arguments). It matches the
tsc
behavior when parsing
.mts
and
.mjs
files.
dts
boolean
, defaults to
false
Added in:
v7.20.0
This option will enable parsing within a TypeScript ambient context, where certain syntax have different rules (like
.d.ts
files and inside
declare module
blocks). Please see
Official Handbook
and
TypeScript Deep Dive
for more information about ambient contexts.
isTSX
boolean
, defaults to
false
Forcibly enables
jsx
parsing. Otherwise angle brackets will be treated as TypeScript's legacy type assertion
var foo = <string>bar;
. Also,
isTSX: true
requires
allExtensions: true
.
jsxPragma
string
, defaults to
React
Replace the function used when compiling JSX expressions. This is so that we know that the import is not a type import, and should not be removed.
jsxPragmaFrag
string
, defaults to
React.Fragment
Replace the function used when compiling JSX fragment expressions. This is so that we know that the import is not a type import, and should not be removed.
onlyRemoveTypeImports
boolean
, defaults to
false
Added in:
v7.9.0
When set to
true
, the transform will only remove
type-only imports
(introduced in TypeScript 3.8). This should only be used if you are using TypeScript >= 3.8.
class A {
declare foo: string; // Removed
bar: string; // Initialized to undefined
prop?: string; // Initialized to undefined
prop1!: string // Initialized to undefined
}
optimizeConstEnums
boolean
, defaults to
false
Added in:
v7.15.0
When set to
true
, Babel will inline enum values rather than using the usual
enum
output:
// Input
const enum Animals {
Fish,
}
console.log(Animals.Fish);
// Default output
var Animals;
(function(Animals) {
Animals[(Animals["Fish"] = 0)] = "Fish";
})(Animals || (Animals = {}));
console.log(Animals.Fish);
// `optimizeConstEnums` output
console.log(0);
This option differs from TypeScript's
--isolatedModules
behavior, which ignores the
const
modifier and compiles them as normal enums, and aligns Babel's behavior with TypeScript's default behavior.
However, when
exporting
a
const enum
Babel will compile it to a plain object literal so that it doesn't need to rely on cross-file analysis when compiling it:
// Input
export const enum Animals {
Fish,
}
// `optimizeConstEnums` output
export var Animals = {
Fish: 0,
};
TypeScript Compiler Options
The official TypeScript compiler has many options for configuring how it compiles and type checks. While many don't apply, some behaviors might be useful and their equivalents in Babel can be enabled by some configuration options or plugins.
--alwaysStrict
You can use the
strictMode
parser option
:
module.exports = {
parserOpts: { strictMode: true },
};
--downlevelIteration
You can use the
@babel/plugin-transform-for-of
plugin. If you are using
@babel/preset-env
,
for...of
is already transpiled using iterators when it isn't supported by your compilation target(s).
--emitDecoratorMetadata
This option isn't supported by an official Babel package since it is a TypeScript-specific addition and not part of the decorators proposal.
If you rely on this feature, you can use the community plugin
babel-plugin-transform-typescript-metadata
.
--esModuleInterop
This is the default behavior of Babel when transpiling ECMAScript modules.
--experimentalDecorators
This option enables support for the "legacy" decorator proposal. You can enable it in Babel using the
@babel/plugin-proposal-decorators
plugin, but please be aware, there are some minor differences.
module.exports = {
plugins: [["@babel/plugin-proposal-decorators", { legacy: true }]],
};
--importHelpers
This is the equivalent of the
@babel/plugin-transform-runtime
package.
---importsNotUsedAsValues
You can use the
onlyRemoveTypeImports
option to replicate this behavior.
onlyRemoveTypeImports: true
is equivalent to
importsNotUsedAsValues: preserve
, while
onlyRemoveTypeImports: false
is equivalent to
importsNotUsedAsValues: remove
. There is no equivalent for
importsNotUsedAsValues: error
.
--inlineSourceMap
You can set the
sourceMaps: "inline"
option in your
babel.config.json
file.
--isolatedModules
This is the default Babel behavior, and it can't be turned off because Babel doesn't support cross-file analysis.
--jsx
JSX support is provided using another plugin.
If you want your output to contains JSX code (i.e.
--jsx preserve
), you need the
@babel/plugin-syntax-jsx
plugin; if you want to transpile it to standard JavaScript (i.e.
--jsx react
or
--jsx react-native
), you should use the
@babel/plugin-transform-react-jsx
plugin.
--jsxFactory
It can be customized using the
pragma
option
of the
@babel/plugin-transform-react-jsx
package. You also need to set the
jsxPragma
option of this plugin.
--module
,
-m
If you are using a bundler (Webpack or Rollup), this option is set automatically.
If you are using
@babel/preset-env
, you can use the
modules
option
; otherwise you can load the specific plugin.
--module
value
|
@babel/preset-env
's
modules
|
Single plugin |
---|---|---|
None
|
false
|
/ |
CommonJS
|
"commonjs"
or
"cjs"
|
@babel/plugin-transform-modules-commonjs
|
AMD
|
"amd"
|
@babel/plugin-transform-modules-amd
|
System
|
"systemjs"
|
@babel/plugin-transform-modules-systemjs
|
UMD
|
"umd"
|
@babel/plugin-transform-modules-umd
|
ES6
or
ES2015
|
false
|
/ |
--outDir
When using
@babel/cli
, you can set the
--out-dir
option
.
--outFile
Babel doesn't support concatenating output files: you should use a bundler (like Webpack, Rollup or Parcel) for that.
When using
@babel/cli
, you can compile a single file using the
--out-file
option
.
--sourceMap
You can use the top-level
sourceMaps: true
option
.
--target
Babel doesn't support targeting a specific version of the language, but you can choose which engines you want to target using
@babel/preset-env
.
If you prefer, you can enable
individual plugins
for every ECMAScript feature.
--useDefineForClassFields
You can use the
setPublicClassFields
assumption to replicate this behavior.
--watch
,
-w
When using
@babel/cli
, you can specify the
--watch
option
.
Caveats
Because there are features of the TypeScript language which rely on the full type-system to be available to make changes at runtime. This section of caveats is quite long, however, it's worth noting that a few of these features are only found in older TypeScript codebases and have modern JavaScript equivalents which you are probably already using.
Since Babel does not type-check, code which is syntactically correct, but would fail the TypeScript type-checking may successfully get transformed, and often in unexpected or invalid ways.
Changes to your
tsconfig.json
are not reflected in babel. The build process will always behave as though
isolatedModules
is turned on, there are Babel-native alternative ways to set a lot of the
tsconfig.json
options
however.
Q
: Why doesn't Babel allow export of a
var
or
let
?
A
: The TypeScript compiler dynamically changes how these variables are used depending on whether or not the value is mutated. Ultimately, this depends on a type-model and is outside the scope of Babel. A best-effort implementation would transform context-dependent usages of the variable to always use the
Namespace.Value
version instead of
Value
, in case it was mutated outside of the current file. Allowing
var
or
let
from Babel (as the transform is not-yet-written) is therefore is more likely than not to present itself as a bug when used as-if it was not
const
.
Impartial Namespace Support
If you have existing code which uses the TypeScript-only
namespace
features. Babel supports a subset of TypeScript's namespace features. If you are considering writing new code which uses namespace, using the ES2015
import
/
export
is recommended instead. It's
not going away
, but there are modern alternatives.
Type-only
namespace
s should be marked with
declare
and will subsequently be safely removed.
export
ing a variable using
var
or
let
in a
namespace
will result in an error:
"Namespaces exporting non-const are not supported by Babel. Change to const or ..."
Workaround
: Use
const
. If some form of mutation is required, explicitly use an object with internal mutability.
namespace
s will not share their scope. In TypeScript, it is valid to refer to contextual items that a
namespace
extends without qualifying them, and the compiler will add the qualifier. In Babel, there is no type-model, and it is impossible to dynamically change references to match the established type of the parent object.
Consider this code:
namespace N {
export const V = 1;
}
namespace N {
export const W = V;
}
The TypeScript compiler compiles it to something like this:
var N = {};
(function(N) {
N.V = 1;
})(N);
(function(N) {
N.W = N.V;
})(N);
While Babel will transform it to something like this:
var N;
(function(_N) {
const V = (_N = 1);
})(N || (N = {}));
(function(_N) {
const W = V;
})(N || (N = {}));
As Babel doesn't understand the type of
N
, the reference to
V
will be
undefined
resulting in an error.
Workaround : Explicitly refer to values not in the same namespace definition, even if they would be in the scope according to TypeScript. Examples:
namespace N {
export const V = 1;
}
namespace N {
export const W = N.V;
}