Skip to content

typescript sometimes uses this at module scope in es6 output #27935

Closed
@dgoldstein0

Description

@dgoldstein0

TypeScript Version: 3.1.3

Search Terms: invalid es6 output this

Code

// a.ts
export const foo = async () => {
  await Promise.resolve();
};

compile with
case 1: tsc --module es6 --target es6 a.ts
case 2: tsc --module es6 --target es5 --importHelpers

(a hybrid - es6 module with es6 target and importHelpers - works fine)

Expected behavior:

this will not be used at module scope in the generated code, since it's not valid es6

Actual behavior:

case 1:

// a.js
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
export const foo = () => __awaiter(this, void 0, void 0, function* () {
    yield Promise.resolve();
});

case 2:

// a.js
var _this = this;
import * as tslib_1 from "tslib";
export var foo = function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
    return tslib_1.__generator(this, function (_a) {
        switch (_a.label) {
            case 0: return [4 /*yield*/, Promise.resolve()];
            case 1:
                _a.sent();
                return [2 /*return*/];
        }
    });
}); };

IMO case 2 is useful for using typescript's es6->5 transpilation with other tools that want es6 module format but don't care about whether the body of the module uses a subset of es6 or not; I expected that the output code would be es6 that was also valid es5 (other than imports & exports) but that turns out not to be the case at the moment.

In both cases we see this is used at module scope. The first case is just objectively broken as this is not valid at the scope it's used in an es6 module which it supposedly is outputting. It's also worth noting that this isn't used in the source code, so ideally typescript would be smart enough to know that __awaiter and __generator don't need it.

Playground Link: can't control the output settings in the playground to give a super useful repro, but the amd output is still interesting: http://www.typescriptlang.org/play/#src=export%20const%20foo%20%3D%20async%20()%20%3D%3E%20%7B%0D%0A%20%20await%20Promise.resolve()%3B%0D%0A%7D%3B

Related Issues: couldn't find any

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptDomain: ES ModulesThe issue relates to import/export style module behavior

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions