Skip to content

Top-level await in TypeScript

The error "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" occurs when trying to use await outside of an async function in TypeScript without proper configuration.

Understanding the Problem

Top-level await allows you to use await at the top level of a module without wrapping it in an async function. This feature requires specific TypeScript compiler settings:

  • module must be set to esnext or system
  • target must be es2017 or higher

Solutions

Method 1: Configure tsconfig.json Properly

Update your tsconfig.json with the correct settings:

json
{
  "compilerOptions": {
    "lib": ["es2020"],
    "module": "es2022",
    "moduleResolution": "node",
    "target": "es2022",
    "outDir": "dist"
  }
}

WARNING

When compiling with tsc filename.ts, TypeScript ignores tsconfig.json. Always compile using tsc without filename arguments to use your configuration.

Method 2: Use tsx for TypeScript Execution

tsx is a modern tool that runs TypeScript files directly without complex setup:

  1. Ensure "type": "module" in your package.json
  2. Install tsx:
bash
npm install tsx
  1. Run your TypeScript file:
bash
npx tsx file.ts

Method 3: Wrap in Async Function (Legacy Approach)

If you can't modify your TypeScript configuration, wrap your await calls:

javascript
const createAccount = async () => {
  const account = await stripe.accounts.create({
    type: 'express',
  });
  return account;
};

createAccount().then(account => {
  // Handle the account object
});

Best Practices

  • Modern Approach: Use tsx for development and proper tsconfig.json settings for production
  • File Extensions: Use .mts extension for ES modules with top-level await
  • Module Resolution: Set "moduleResolution": "node" for Node.js environments

TIP

Top-level await is natively supported in modern Node.js versions (v14.8+). Ensure you're using a recent Node.js version for best compatibility.

Common Pitfalls

  • Compiling with tsc filename.ts instead of just tsc
  • Missing "type": "module" in package.json
  • Using outdated Node.js versions that don't support ES modules

By following these solutions, you can successfully use top-level await in your TypeScript projects with proper configuration and tooling.