Skip to content

Top-level await error message is extremely unclear #36036

@DanielRosenwasser

Description

@DanielRosenwasser
Member
// @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".

Activity

rbuckton

rbuckton commented on Jan 6, 2020

@rbuckton
Contributor

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

DanielRosenwasser

DanielRosenwasser commented on Jan 6, 2020

@DanielRosenwasser
MemberAuthor

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.
rbuckton

rbuckton commented on Jan 6, 2020

@rbuckton
Contributor

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

rbuckton

rbuckton commented on Jan 6, 2020

@rbuckton
Contributor

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?

DanielRosenwasser

DanielRosenwasser commented on Jan 6, 2020

@DanielRosenwasser
MemberAuthor

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

rbuckton

rbuckton commented on Jan 6, 2020

@rbuckton
Contributor

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.

sheetalkamat

sheetalkamat commented on Jan 6, 2020

@sheetalkamat
Member

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...

rbuckton

rbuckton commented on Jan 6, 2020

@rbuckton
Contributor

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

rbuckton

rbuckton commented on Jan 6, 2020

@rbuckton
Contributor

@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?

DanielRosenwasser

DanielRosenwasser commented on Jan 6, 2020

@DanielRosenwasser
MemberAuthor

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

rbuckton

rbuckton commented on Jan 7, 2020

@rbuckton
Contributor

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}'
rbuckton

rbuckton commented on Jan 13, 2020

@rbuckton
Contributor

@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?

DanielRosenwasser

DanielRosenwasser commented on Jan 13, 2020

@DanielRosenwasser
MemberAuthor

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

dilyanpalauzov

dilyanpalauzov commented on Dec 4, 2021

@dilyanpalauzov

After struggling with error error TS1378: Top-level 'await' expressions are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', or 'nodenext', and the 'target' option is set to 'es2017' or higher. for long time, I found this thread. I solved my problem by adding export {}; to my file. I do use ES6 modules, but this particular file does not need any exports.

Please adjust the error message to provide a hint, that apart from adjusting the module and target parameters, the concrete file needs an export {}; line.

serg06

serg06 commented on Feb 24, 2022

@serg06

It fixed for me when I changed "module": "ESNext" to "module": "es2022".

Qix-

Qix- commented on Feb 27, 2022

@Qix-

Yeah @serg06 is right here. Why do ESNext and nodenext not work? Aggravating.

avin-kavish

avin-kavish commented on Aug 10, 2022

@avin-kavish

Why do we still need to add export {} to mark it as a module, why can't it implicitly be one when type: "module" is set?

DanielRosenwasser

DanielRosenwasser commented on Aug 10, 2022

@DanielRosenwasser
MemberAuthor

module doesn't always imply that you don't have any globals in your program.

If that's not the behavior you want, in newer versions of TypeScript, you can configure this with the moduleDetection option and set it to force.

jimmywarting

jimmywarting commented on May 15, 2023

@jimmywarting
Contributor

Also think having a export {} is unnecessary. should just remove that warning all together i think.
just having a top level await should assume that it's of type=module
top level await should act the same way as having export {} in the code.

More and more ppl are starting to use ESM, so your assumption that ppl use cjs or script by default is, Meh.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

    Development

    Participants

    @Qix-@DanielRosenwasser@jimmywarting@serg06@rbuckton

    Issue actions

      Top-level `await` error message is extremely unclear · Issue #36036 · microsoft/TypeScript