TypeStrong / ts-node

TypeScript execution and REPL for node.js
https://typestrong.org/ts-node
MIT License
12.9k stars 534 forks source link

ESM mode does not properly infer config `target` from `"module": "node*"` #1900

Open nickserv opened 2 years ago

nickserv commented 2 years ago

Search Terms

Expected Behavior

Using "module": "node16" or "module": "nodenext" sets target to es2017 or newer and compiles without an error. This is what happens if you use tsc instead of ts-node --esm.

Actual Behavior

target is set to the default of es5, causing the following error:

/usr/local/lib/node_modules/ts-node/src/index.ts:859
    return new TSError(diagnosticText, diagnosticCodes, diagnostics);
           ^
TSError: ⨯ Unable to compile TypeScript:
index.ts:8:5 - error TS1432: Top-level 'for await' loops are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', or 'nodenext', and the 'target' option is set to 'es2017' or higher.

8 for await (const name of getBeatles()) console.log(name)
      ~~~~~

    at createTSError (/usr/local/lib/node_modules/ts-node/src/index.ts:859:12)
    at reportTSError (/usr/local/lib/node_modules/ts-node/src/index.ts:863:19)
    at getOutput (/usr/local/lib/node_modules/ts-node/src/index.ts:1077:36)
    at Object.compile (/usr/local/lib/node_modules/ts-node/src/index.ts:1433:41)
    at transformSource (/usr/local/lib/node_modules/ts-node/src/esm.ts:400:37)
    at /usr/local/lib/node_modules/ts-node/src/esm.ts:278:53
    at async addShortCircuitFlag (/usr/local/lib/node_modules/ts-node/src/esm.ts:409:15)
    at async nextLoad (node:internal/modules/esm/loader:163:22)
    at async ESMLoader.load (node:internal/modules/esm/loader:601:20)
    at async ESMLoader.moduleProvider (node:internal/modules/esm/loader:457:11) {
  diagnosticCodes: [ 1432 ]
}

Steps to reproduce the problem

Use "module": "node16" or "module": "nodenext" without target and with "type": "module" in package.json.

Minimal reproduction

// index.ts
async function* getBeatles() {
  yield "John"
  yield "Paul"
  yield "George"
  yield "Ringo"
}

for await (const name of getBeatles()) console.log(name)

ts-node --esm index.ts

Specifications

cspotcode commented 2 years ago

I'm guessing this is the culprit.

https://github.com/TypeStrong/ts-node/blob/8b09d49b26c1c25e34133b857c073729dd691f11/src/configuration.ts#L45-L48

Probably this logic made more sense in the past, but things have changed since then.

cspotcode commented 2 years ago

While we're at it we can look at this, too.

https://github.com/TypeStrong/ts-node/blob/8b09d49b26c1c25e34133b857c073729dd691f11/src/configuration.ts#L50

I don't remember off-hand but I think there are situations where you need to specify module and moduleResolution, when one should be sufficient to imply the other.