Typescript: Top-level `await` error message is extremely unclear

Created on 6 Jan 2020  ·  13Comments  ·  Source: microsoft/TypeScript

// @target: es2017
// @module: esnext

await 100;

This gives the following error message:

'await' outside of an async function is only allowed at the top level of a module when '--module' is 'esnext' or 'system' and '--target' is 'es2017' or higher.

This is really unclear! My compiler options are all set correctly, so why is this not working?

It's because it's not a module. This error message is expecting me to meet 3 different conditions, "top level of a module" is unclear for any user who just wants to use this feature. They'll likely take "module" to just mean "file".

Error Messages Experience Enhancement

Most helpful comment

Personally, I'd prefer just one at a time, but both are fine at once.

I'm generally not a fan of fixing one error just to end up with another error when the fix had nothing to do with the second error. I'd rather get both so I know all the actions I need to take.

All 13 comments

Yeah, this is a tough one to write concisely. Do you have a better suggestion?

When it occurs at the top level of a file (not a regular function), regardless of compiler options:

`await` expressions are only allowed at the top level of a file when that file is a module, but this file has no imports or exports. Consider adding an empty 'export {}' to make this file a module.

and when the options are wrong:

Top level 'await' expressions are only allowed when the 'module' option is set to 'esnext' or 'system', and the 'target' option is set to 'es2017' or higher.

When in a regular function

'await' expressions are only allowed within async functions and at the top levels of modules.

Would you report both of the top two errors if both are a problem?

Should we have a codefix for the first one to add an export {} to the file?

Also, have we considered adding codefixes to fix the tsconfig.json for things like the 2nd error message?

Would you report both of the top two errors if both are a problem?

Personally, I'd prefer just one at a time, but both are fine at once.

Should we have a codefix for the first one to add an export {} to the file?

Always!

Also, have we considered adding codefixes to fix the tsconfig.json for things like the 2nd error message?

I think we do, but check with @sheetalkamat

Personally, I'd prefer just one at a time, but both are fine at once.

I'm generally not a fan of fixing one error just to end up with another error when the fix had nothing to do with the second error. I'd rather get both so I know all the actions I need to take.

Also, have we considered adding codefixes to fix the tsconfig.json for things like the 2nd error message?

No we haven't done that yet and there is #30739 that needs something similar...

Actually, it looks like we have. We have fixes already for enabling jsx (services/codefixes/fixEnableJsxFlag.ts) and experimentalDecorators (services/codefixes/fixEnableExperimentalDecorators.ts).

@DanielRosenwasser: Having a codefix to change your module to system when its currently set to commonjs seems possibly bad as those module systems are incompatible. Should we still have the quick fix, or should we only have one for module: es2015 -> module: esnext?

es2015 to esnext, especially since moduleResolution can change when changing from commonjs

What do you think of these code fix names?

For 'await' expressions are only allowed at the top level of a file when that file is a module, but this file has no imports or exports. Consider adding an empty 'export {}' to make this file a module.:

  • Add 'export {}' to make this file into a module.

For Top level 'await' expressions are only allowed when the 'module' option is set to 'esnext' or 'system', and the 'target' option is set to 'es2017' or higher.:

  • Set the 'module' option in your configuration file to '{0}', and the 'target' option to '{1}' (if both are invalid and fixable)
  • Set the 'module' option in your configuration file to '{0}' (if module or both are invalid and fixable)
  • Set the 'target' option in your configuration file to '{0}' (if target or both are invalid and fixable).

I like being able to do both in one action, but Set the 'module' option in your configuration file to '{0}', and the 'target' option to '{1}' seems very wordy. I'm tempted to use a message like this instead:

tsconfig.json: Set 'module' to '{0}' and 'target' to '{1}'

@DanielRosenwasser:

Consider the following:

// file.ts
await 1;
export {};

// tsconfig.json
{ "compilerOptions": { "target": "es5" } }

We would be able to fix the "target" as "es2017", but we can't fix the "module" (which is "commonjs" by default here). Should we even offer a codefix for "target" if we won't be able to fix "module" later?

I think it's fine to say "no, we can't give a quick fix in all cases", and that might be one of them

Was this page helpful?
0 / 5 - 0 ratings

Related issues

wmaurer picture wmaurer  ·  3Comments

fwanicka picture fwanicka  ·  3Comments

weswigham picture weswigham  ·  3Comments

zhuravlikjb picture zhuravlikjb  ·  3Comments

Antony-Jones picture Antony-Jones  ·  3Comments