Skip to content

computed keys with private element and super call should not be hoisted when targeted to ES2022 #56754

Open
@JLHwung

Description

@JLHwung

🔎 Search Terms

Private element, computed key, super call

🕗 Version & Regression Information

  • This is a crash
  • This changed between versions ______ and _______
  • This changed in commit or PR _______
  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about Classes
  • I was unable to test this on prior versions because _______

⏯ Playground Link

https://www.typescriptlang.org/play?target=9#code/DYUwLgBAxghgDmArgJxAEwGIHssEEpQgDORANBKkYsGANwBQUwMJEAQhAN70TRYB2RMMkRQwWZAAoAbgEouPXtHhJUmHPkKsAvBGmKAvvSP1+IAO7RmrAMIQQADzAh+aIuwW8oAoSLETJeW4lKxZ3XE8QiCEYMABLKAgAYgAzHAhdABYAJgYo6LBYhIgAbSo4EClJMHltAD4IMAA6VJxZAF08pQMu3kpqSF1YBBR0bDwCYiJJXFlaXkNjekYfLFAm4CwAc0lOCmIBiAM5oA

💻 Code

let capturedFooAccess, result;
class B {
  constructor(v) {
    capturedFooAccess = v
  }
}

new class C extends B {
  constructor() {
    class A {
      static #foo = 42;
      static [super((t) => t.#foo)];
    };
    result = capturedFooAccess(A);  
  }
}

console.log({ result });

🙁 Actual behavior

The transformed code throws "Private field '#foo' must be declared in an enclosing class" because the private key IIFE is hoisted before class A.

🙂 Expected behavior

It should print { result: 42 }

The input is already ES2022, TS could have left it as-is.

Additional information about the issue

We can dodge this issue in ES2022 target, but I haven't figured out how to deal with the decorator expression. Either we lost the #foo access or the super() is moved to the scope of the underived class A.

let capturedFooAccess, result;
class B {
  constructor(v) {
    capturedFooAccess = v
  }
}

new class C extends B {
  constructor() {
    class A {
      @(super((t) => t.#foo), v => v) #foo = 42;
    };
    result = capturedFooAccess(A);  
  }
}

console.log({ result });

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptEffort: ModerateRequires experience with the TypeScript codebase, but feasible. Harder than "Effort: Casual".

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions