Skip to content

support for useDefineForClassFields #785

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

Open
tmm1 opened this issue Apr 10, 2025 · 11 comments
Open

support for useDefineForClassFields #785

tmm1 opened this issue Apr 10, 2025 · 11 comments

Comments

@tmm1
Copy link
Contributor

tmm1 commented Apr 10, 2025

hoping for some pointers on how to start about fixing this:

❯ cat test.ts
class Point {
    x: number = 2;
    y: number;
}

❯ tsgo tsc -t es2020 /tmp/test.ts && cat /tmp/test.js
Files:               52
Types:               17794
class Point {
    x = 2;
    y;
}

❯ npx --package typescript tsc -t es2020 /tmp/test.ts && cat /tmp/test.js
class Point {
    constructor() {
        this.x = 2;
    }
}
@tmm1
Copy link
Contributor Author

tmm1 commented Apr 10, 2025

for reasons that are not clear to me, in the vscode codebase the generated syntax is es2020 style even though the tsconfig says es2022

❯ cd vscode
❯ grep es20 src/tsconfig.*
src/tsconfig.base.json:         "target": "es2022",

❯ echo 'class Point { x: number = 2; }' > src/point.ts
❯ npm run gulp compile-client
❯ cat out/point.js
"use strict";
class Point {
    constructor() {
        this.x = 2;
    }
}

@tmm1
Copy link
Contributor Author

tmm1 commented Apr 10, 2025

is the printer the right place for this?

diff --git i/internal/printer/printer.go w/internal/printer/printer.go
index 7b65f042a..1dee8bc9c 100644
--- i/internal/printer/printer.go
+++ w/internal/printer/printer.go
@@ -2843,6 +2843,7 @@ func (p *Printer) emitSpreadElement(node *ast.SpreadElement) {
 }
 
 func (p *Printer) emitClassExpression(node *ast.ClassExpression) {
+	target := p.currentSourceFile.LanguageVersion
 	state := p.enterNode(node.AsNode())
 	p.generateNameIfNeeded(node.Name())
 
@@ -2863,7 +2864,13 @@ func (p *Printer) emitClassExpression(node *ast.ClassExpression) {
 	p.writePunctuation("{")
 	p.pushNameGenerationScope(node.AsNode())
 	p.generateAllMemberNames(node.Members)
-	p.emitList((*Printer).emitClassElement, node.AsNode(), node.Members, LFClassMembers)
+	if target >= core.ScriptTargetES2022 {
+		p.emitList((*Printer).emitClassElement, node.AsNode(), node.Members, LFClassMembers)
+	} else {
+		// !!!
+		// add constructor declaration if missing
+		// move property decls into constructor body?
+	}
 	p.popNameGenerationScope(node.AsNode())
 	p.writePunctuation("}")
 

EDIT: would need to handle emitClassExpression too

@tmm1
Copy link
Contributor Author

tmm1 commented Apr 10, 2025

okay i see there is a transformation layer, so maybe this belongs in ESModuleTransformer or RuntimeSyntaxTransformer

@tmm1
Copy link
Contributor Author

tmm1 commented Apr 10, 2025

I think I misdiagnosed my issue and I don't actually need es2020 compat classes. Something else is causing generated JS not to load.

@tmm1 tmm1 closed this as completed Apr 10, 2025
@tmm1
Copy link
Contributor Author

tmm1 commented Apr 10, 2025

for reasons that are not clear to me

"useDefineForClassFields": false

cc microsoft/vscode#186726

@tmm1 tmm1 reopened this Apr 10, 2025
@tmm1 tmm1 changed the title es2020 support for classes support for useDefineForClassFields Apr 10, 2025
@jakebailey
Copy link
Member

jakebailey commented Apr 10, 2025

None of the downleveling is supported yet.

@tmm1
Copy link
Contributor Author

tmm1 commented Apr 10, 2025

makes sense. the other issue i ran into was decorators being emitted.

@jakebailey
Copy link
Member

Right, that'd be the esnext transform which removes it.

@tmm1
Copy link
Contributor Author

tmm1 commented Apr 16, 2025

https://github.com/microsoft/TypeScript/blob/0693cc72e6ddb6c7468a14e05888efa2f43ac7b0/src/compiler/transformer.ts#L145-L153

    if (languageVersion < ScriptTarget.ESNext) {
        transformers.push(transformESNext);
    }

    if (!compilerOptions.experimentalDecorators && (languageVersion < ScriptTarget.ESNext || !useDefineForClassFields)) {
        transformers.push(transformESDecorators);
    }

    transformers.push(transformClassFields);

not clear what the equivalent of this is on the golang side. maybe func (e *emitter) getScriptTransformers()

@jakebailey
Copy link
Member

getScriptTransformers is the closest, yes, but we still do not have any of the other transforms. I would not recommend using our emit yet; it's not ready outside limited syntax outside pure type erasure and some enum stuff.

@tmm1
Copy link
Contributor Author

tmm1 commented Apr 29, 2025

#819 added an esnext transform into a new internal package, so now there's a more obvious place to add classFields and decorator support in transformers.GetScriptTransformers

// !!! transform native decorator syntax
// !!! transform class field syntax

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants