-
-
Notifications
You must be signed in to change notification settings - Fork 33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How do I use babel for decorators instead of TS? #174
Comments
Did some more digging, the tslib's decorator implementation looks very similar to the legacy babel implementation: // output from tslib
function __decorate(decorators, target, key, desc) {
var c = arguments.length,
r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc,
d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
r = Reflect.decorate(decorators, target, key, desc);
else
for (var i = decorators.length - 1; i >= 0; i--)
if (d = decorators[i])
r = (
c < 3
? d(r)
: c > 3
? d(target, key, r)
: d(target, key)
) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
}
export { __decorate as _ }; import { _ as __decorate } from '../../tslib.es6-ddb164bc.js';
import { tracked } from '@glimmer/tracking';
class Demo extends Component {
// ...
}
__decorate([tracked], Demo.prototype, "active", void 0); And interop with the assumed-to-be-compiled-by-babel decorator (tracked) and this code from my test library seems to be ok? but, I suppose my question still remains though -- since babel can handle this, how do we let babel handle this? |
Hi there. You're right that decorators are also being standardized as part of TC39 and finally seem to be coming along nicely. But as of today, TypeScript decorators are still treated by TypeScript as part of the TypeScript superset (like enums), and is still something you opt in to use with the That is why decorators are removed from TypeScript even when you target ESNext. There is in fact no way to preserve them after the TypeScript compiler has been doing its thing such that other tools, like Babel, can enter in a later step and transform the decorator syntax. To better understand this, imagine running However, this will all probably change now that decorators have entered stage 3 in the standards process. When it eventually arrives in stage 4 and becomes part of the next major version of EcmaScript, potentially ES2023, then TypeScript decorators will align with the standardized feature and be preserved when you target ESNext or ES2023 as the target of a tsconfig, and by then tools like I hope this explanation makes sense. If not, feel free to comment again, and I'll gladly elaborate. |
@wessberg that explanation does indeed make sense and is in fact eminently reasonable. However, there are a number of cases where you need to use TS for type checking while using Babel (or other tools) for emit for decorators. A key example here—and the motivating one for @NullVoxPopuli's comment—is the entire Ember ecosystem, which standardized on using the Babel legacy decorator transform and indeed using Babel for all emit (using TS only for type checking) back in 2018 precisely because of the interop hazards that exist when trying to use both Babel and TS's decorators. The bugs are many and subtle! Given that (a) TypeScript has yet to implement support for the Stage 3 decorators proposal, and the earliest we'd expect to see it is in TS 4.8, coming in mid-August; (b) there is not yet any clear migration path for existing users of the legacy transforms for either Babel or TypeScript; and (c) there are many users who rely on the ability to do all emit via Babel etc., rather than using |
Hi there @chriskrycho. I guess it would make sense to support delegating the full responsibility of syntax transformation to whatever transpiler has been chosen, such as babel. It could lead to some performance gains, albeit minor, since a TypeScript builder program would still be constructed based on the source file(s), since it is needed not just for diagnostics, but especially so for declaration files (which too need a proper type checker for the relationships between TS symbols to be correct in the declaration bundling phase). In fact, I can see some value in not even exposing this as a config option, but enabling this behavior by default if What do you think about a solution such as this one? |
I think the default should be to use only the specified transpiler for emitting code if a non- I would very much prefer “good defaults, no magic, configurable if the defaults don’t fit with your needs.” |
If we do it like that, then we will have to add I'm very much in agreement with you generally in terms of magic. For In terms of the "good, but overridable defaults" principle, in practice here what tends to happen is that people bring in their babel configs from other projects, and these very often come with configuration options that simply won't produce great Rollup bundles. And instead of writing a ton of documentation of best practices and which options to disable when combining with Rollup, it has been a good solution to forcefully ignore some of those options that simply don't play work well with this integration. There are other examples of magic too, such as splitting babel configs into two if babel-minify plugins are identified, to ensure that the minification related plugins only run once per chunk, whereas others run once per file. All this to say that where I tend to do the opposite with other libraries, with Okay, sorry for the wall of text there. But that's the context. I'm still fairly sure I would prefer a default behavior of only doing the full emit with Babel if I can find // It can be a string
{
transpiler: "babel"
}
// But it can also be a record
{
transpiler: {
typescriptSyntax: "typescript",
otherSyntax: "babel"
}
} With that option, we're back to fully allowing customizing the transpilation behavior, while still retaining good defaults and respecting the input babel/swc configs as much as possible while still ignoring the ones that could break Rollup or produce inefficient bundles. How does that sound? |
This has been implemented as part of v3.0.0. What I ended up implementing was a solution in which the chosen transpiler is used for the entire syntax transformation. I also ended up marking This behavior is fully customizable, since the transpiler option now optionally takes an options record, as described above. This means that transpilers can be mixed, e.g.: transpiler: {
typescriptSyntax: "typescript",
otherSyntax: "babel"
} When mixed like so, |
Outstanding. Thank you! |
I tested the new release, with regard to the problem discussed here, and it worked perfectly! Thanks so much @wessberg 🙏 |
Anyone see anything obvious I did wrong here? https://github.com/NullVoxPopuli/ember-popperjs/pull/166/files I still get:
|
so |
That's correct, However, I've come to realize there's actually no need to enforce As for the warning about |
Question
This part of the documentation says that typescript is used for TS-specific features..
but decorators are not TS-specific.
TS decorators are different from the
@babel/plugin-proposal-decorators
output -- how can I use this babel plugin for decorators instead of TS (forcing atslib
dependency, which I don't want 😅 )My babel config:
my ts setup:
The text was updated successfully, but these errors were encountered: