How to enable top-level await in typescript/node/stencil js/jsx

4.8k Views Asked by At

How to enable top-level await in typescript? What are the tsconfig settings? I've tried the common ones such as esnext in module and target es2017 or higher. Can the top level await be in a ts file or does it have to be in another file such as mjs or js?

I'm using node and stencil js along with typescript.

I continue to get this error: Module format cjs does not support top-level await. Use the "es" or "system" output formats rather.

In tsconfig ive tried common settings such as esnext in module and target es2017 or higher.

I export to be able to export a object without a promise.

Example

    export class Hello{
    static async SayHello() {
      return new Promise(resolve => { resolve("Hello World")})
        }
    }

    export const hello = await Hello.SayHello(); 


    //in another ts file 
    import {hello} from 'Hello.ts' 
    console.log(hello); 
2

There are 2 best solutions below

3
Kleywalker On

Hi!

I created the following files:

package.json

{
  "name": "hello",
  "version": "1.0.0",
  "description": "",
  "type": "module",
  "main": "index.js",
  "scripts": {
    "build": "tsc"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "typescript": "^5.0.3"
  }
}

tsconfig.json

{
  "compilerOptions": {
    "module": "esnext",
    "moduleResolution": "node",
    "outDir": "dist",
    "rootDir": "src",
    "target": "es2017"
  },
  "exclude": ["dist", "node_modules"]
}

src/Hello.ts

export class Hello {
  static async SayHello() {
    return new Promise((resolve) => {
      resolve("Hello World");
    });
  }
}

export const hello = await Hello.SayHello();

src/index.ts

import { hello } from "./Hello";
console.log("test");
console.log(hello);

This seems to do the trick.

That being said are you sure that you want to export SayHello as a function and not the entire class Hello?

1
Kleywalker On

I'm not sure, you probably could change the filename from toplevelawaitissue.tsto toplevelawaitissue.cts but then you have to add a new import. Not quite the solution you are looking for. Perhaps someone could clarify this.

If it fits your requirements you should change your code to:

toplevelawaitissue.ts

export const message = async () => await Promise.resolve('Hello World');

my-component.tsx

import { Component, Prop } from '@stencil/core';
// import { format } from '../../utils/utils';
import { message } from '../../utils/toplevelawaitissue';

@Component({
  tag: 'my-component',
  styleUrl: 'my-component.css',
  shadow: true,
})
export class MyComponent {
  /**
   * The first name
   */
  @Prop() first: string;

  /**
   * The middle name
   */
  @Prop() middle: string;

  /**
   * The last name
   */
  @Prop() last: string;

  // private getText(): string {
  //   return format(this.first, this.middle, this.last);
  // }

  async render() {
    // return <div>Hello, World! I'm {this.getText()}</div>;
    return await message();
  }
}

This would be the proper why as it awaits the message when its needed. Again: If it fits your requirements.