Typescript: Class parameter properties aren't compiled correctly when transformed after preset-env
See original GitHub issueBug Report
Current behavior
When @babel/preset-typescript
is placed before @babel/preset-env
in the presets array and @babel/preset-env
is configured to transform classes (by setting target to include ie 11), class parameter properties are not transpiled which will cause runtime exceptions.
Input Code
class Foo {
constructor(public bar: number) {}
}
compiles to:
"use strict";
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var Foo = function Foo(bar) {
_classCallCheck(this, Foo);
};
.babelrc.json
{
"presets": [
"@babel/typescript",
["@babel/env", {
"targets": "ie 11"
}]
]
}
The same result can be produced by using the @babel/transform-classes
plugin directly:
$ babel --no-babelrc --plugins @babel/transform-classes,@babel/transform-typescript test.ts
Expected behavior With the preset order reversed, it successfully compiles down to:
"use strict";
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var Foo = function Foo(bar) {
_classCallCheck(this, Foo);
this.bar = bar;
};
Possible Solution This seems to be a limitation of plugin ordering where the class is compiled down to a function by preset-env before typescript can properly transform the parameter properties and does not look like it can easily be fixed. I suggest documenting this plugin ordering issue under the typescript preset/plugin docs so that people are aware of it since babel/preset-env is a very common preset that people will be using with typescript.
Issue Analytics
- State:
- Created 3 years ago
- Reactions:3
- Comments:7 (1 by maintainers)
As of https://babeljs.io/docs/en/presets#preset-ordering order matters.
https://babeljs.io/docs/en/presets#preset-ordering
The preset is (unintuitively) applied from last to first. It was for backward compatibility back to 2015 when people use
preset-es2015
andpreset-latest
in this order:["preset-es2015", "preset-latest"]
It is correct that
typescript
preset should be applied before other ES language features, sopreset-typescript
should be placed afterpreset-env
. I will update the preset-typescript and preset-flows about the ordering issues.It is hard for Babel to warn about a certain preset order because Babel can’t statically know the usage of preset, for example:
We could warn for the builtin
preset-env
andpreset-typescript
, but we couldn’t do it in a general way.