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
Typescript: always strip declare from class fields #11747
Typescript: always strip declare from class fields #11747
Conversation
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit 6a82099:
|
Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/24966/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks.
@DanielRosenwasser Was making |
At least from the perspective of the Ember world, it's extremely helpful. Ember makes heavy use of dependency injection using decorators, like so: import Component from '@glimmer/component';
import { inject as service } from '@ember/service';
import type Session from 'my-app/services/session';
export default class Profile extends Component {
@service declare session: Session;
} The TS implementation gives us all the desired semantics here: the item can be declared for decoration, but because it has |
Is there any concern with leaving the property in and how that would interact with other transforms for class fields? For example, in TS the |
@rbuckton doesn't declare prevent emit in the constructor even without But a decorated declare always ends up decorated (even with If |
I have played a bit with TS's playground and even if this doesn't match TS's behavior* it's probably a good compromise. * Babel's decorators and TypeScript's decorators have two completely different implementations. TypeScript applies fields decorators on the prototype, while Babel applies them on the instance. This means that, for example, this code has two different behaviors: class A {
x = 1;
}
class B extends A {
@nonconfigurable declare x: number;
} With TS, The longer-term solution (Babel 8?) would be to publish a new
Can you add this test? class Foo {
@decorator declare bar: string;
} "transform-typescript" { allowDeclareFields: true }
"proposal-decorators" { legacy: true }
"proposal-class-properties" |
@nicolo-ribaudo test added |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want to restate that I don't like this PR 😛
However, I think that it's the best we can have for now.
FWIW, I think we’ll all be happier once it’s nicely resolved, assuming someday decorators are nicely resolved. 😜 |
Normally, a class field annotated with
declare
would be stripped becausedeclare
indicates this is type-only information. The exception is when a decorator is also applied to the property, e.g.In this case, the property should be preserved so that the decorator can do its thing. Currently
babel-plugin-transform-typescript
is correctly not stripping the property, but it is also not stripping thedeclare
.This PR fixes this by always removing
declare
if still found if the path has not been removed.This matches the behavior of the TypeScript compiler: https://www.typescriptlang.org/play/?experimentalDecorators=true#code/MYGwhgzhAEBiD29oG8CwAoa0ACATApsPAE5gAuJ0BoYx+0AZogFzQRnECWAdgOYDcGLNXB1oAI1qt2XPoPQBfIA
I've pushed a failing test first to demonstrate the issue and then pushed the fix.