TypeScript icon indicating copy to clipboard operation
TypeScript copied to clipboard

Invalid transform of `async` arrow expression containing `super`

Open evanw opened this issue 4 years ago • 2 comments

Bug Report

🔎 Search Terms

super property setter getter method lowered async arrow function expression generator

🕗 Version & Regression Information

  • This is the behavior in every version I tried

⏯ Playground Link

Playground link with relevant code

💻 Code

class Base {
  set setter(x: string) {}
  get getter() { return '' }
  method(x: string) {}

  static set setter(x: number) {}
  static get getter() { return 0 }
  static method(x: number) {}
}

class Derived extends Base {
  a() { return async () => super.method('') }
  b() { return async () => super.getter }
  c() { return async () => super.setter = '' }

  static a() { return async () => super.method(0) }
  static b() { return async () => super.getter }
  static c() { return async () => super.setter = 0 }
}

🙁 Actual behavior

Here's the above code compiled by TypeScript with a target of ES2015:

class Base {
    set setter(x) { }
    get getter() { return ''; }
    method(x) { }
    static set setter(x) { }
    static get getter() { return 0; }
    static method(x) { }
}
class Derived extends Base {
    a() { return () => __awaiter(this, void 0, void 0, function* () { return super.method(''); }); }
    b() { return () => __awaiter(this, void 0, void 0, function* () { return super.getter; }); }
    c() { return () => __awaiter(this, void 0, void 0, function* () { return super.setter = ''; }); }
    static a() { return () => __awaiter(this, void 0, void 0, function* () { return super.method(0); }); }
    static b() { return () => __awaiter(this, void 0, void 0, function* () { return super.getter; }); }
    static c() { return () => __awaiter(this, void 0, void 0, function* () { return super.setter = 0; }); }
}

The resulting code contains syntax errors:

Uncaught SyntaxError: 
    a() { return () => __awaiter(this, void 0, void 0, function* () { return super.method(''); }); }
                                                                             ^

'super' keyword outside a method

🙂 Expected behavior

I expected the uses of super inside async arrow expressions to be transformed into a helper function similarly to how TypeScript currently transforms super inside async methods. Perhaps TypeScript's output would look something like this instead:

class Base {
    set setter(x) { }
    get getter() { return ''; }
    method(x) { }
    static set setter(x) { }
    static get getter() { return 0; }
    static method(x) { }
}
class Derived extends Base {
    a() {
        const _super = Object.create(null, { method: { get: () => super.method } });
        return () => __awaiter(this, void 0, void 0, function* () { return _super.method.call(this, ''); });
    }
    b() {
        const _super = Object.create(null, { getter: { get: () => super.getter } });
        return () => __awaiter(this, void 0, void 0, function* () { return _super.getter; });
    }
    c() {
        const _super = Object.create(null, { setter: { get: () => super.setter, set: v => super.setter = v } });
        return () => __awaiter(this, void 0, void 0, function* () { return _super.setter = ''; });
    }
    static a() {
        const _super = Object.create(null, { method: { get: () => super.method } });
        return () => __awaiter(this, void 0, void 0, function* () { return _super.method.call(this, 0); });
    }
    static b() {
        const _super = Object.create(null, { getter: { get: () => super.getter } });
        return () => __awaiter(this, void 0, void 0, function* () { return _super.getter; });
    }
    static c() {
        const _super = Object.create(null, { setter: { get: () => super.setter, set: v => super.setter = v } });
        return () => __awaiter(this, void 0, void 0, function* () { return _super.setter = 0; });
    }
}

evanw avatar Nov 16 '21 19:11 evanw

is this issue https://github.com/microsoft/TypeScript/issues/44515 possibly related, or affecting the same/similar code paths?

dnalborczyk avatar Nov 17 '21 03:11 dnalborczyk

I also ran into this issue. Are there any suggested workarounds? I need my function to be an arrow function, so I can't change that.

cabillin avatar Sep 13 '22 22:09 cabillin