#`export class` error with verbatimModuleSyntax?

19 messages · Page 1 of 1 (latest)

acoustic glen
#

I'm trying to export a simple class, like so:

foo.ts
export class Foo {...}

I'm getting the following error message:

A top-level 'export' modifier cannot be used on value declarations in a CommonJS module when 'verbatimModuleSyntax' is enabled.

I'm using verbatimModuleSyntax based on advice from here: https://www.totaltypescript.com/tsconfig-cheat-sheet
I read the description of it (https://www.typescriptlang.org/tsconfig/#verbatimModuleSyntax) and it seems like a good idea, but I do not understand why it would cause this error. I am not trying to create a CommonJS module, I'm just trying to create a normal Typescript module.

I've also tried to read up on Typescript modules, but haven't found anything relating to my problem. I have seen several examples like export class Foo with no mention of any caveats or catches.

mystic bramble
#

@acoustic glen CommonJS means that your code is compiling to require and module.exports and unlike ESM, CJS only really has a single export.

#

Normally TS compiles ESM to CJS in a sort of synthetic way, if you do;

export const foo = "foo";
export const bar = "bar";
export default "default";

TS will make something like:

module.exports = { 
    __esModule: true,
    foo: "foo",
    bar: "bar",
    default: "default"
}
#

But the point of "verbatim" modules is "what you see is what you get" so that sort of transformation isn't allowed.

#

That's stated in the description of the tsconfig flag you linked, though admitedly it's under all the import type stuff:

With this new option, what you see is what you get.

That does have some implications when it comes to module interop though. Under this flag, ECMAScript imports and exports won’t be rewritten to require calls when your settings or file extension implied a different module system. Instead, you’ll get an error.

#

To be clear this has nothing to do with class, you get the same error on the simple string example from above:

mortal laurelBOT
#
retsam19#0

Preview:ts export const foo = "foo" export const bar = "bar" export default "default"

mystic bramble
#

Anyway, you should probably either target ESM, or drop verbatimModuleSyntax or both.

#

Migrating to ESM is something most people would recommend doing anyway (though you may have to change more than just your output setting) and personally I don't think verbatimModuleSyntax is that helpful - it's mostly a style thing of whether you like the type modifier - and there's a lot of misinformation about it.

acoustic glen
#

I don't think verbatimModuleSyntax forces that?

#

I don't see anywhere in my code or configuration where I would be asking to compile to CommonJS. So I am quite confused.

rugged tapir
#

What does your tsconfig look like?

acoustic glen
#
  "include": [
    "./**/*.ts",
    "../shared/**/*.ts"
  ],
  "compilerOptions": {
    "baseUrl": "../",
    "rootDir": "../",

    /* Base Options: */
    "esModuleInterop": true,
    "skipLibCheck": true,
    "target": "es2023",
    "allowJs": true,
    "resolveJsonModule": true,
    "moduleDetection": "force",
    "isolatedModules": true,
    "verbatimModuleSyntax": true,

    /* Strictness */
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitOverride": true,

    /* If transpiling with TypeScript: */
    "module": "NodeNext",
    "outDir": "dist",
    "sourceMap": true,

    /* AND if you're building for a library: */
    "declaration": true,

    /* AND if you're building for a library in a monorepo: */
    "composite": true,
    "declarationMap": true,

    /* If your code doesn't run in the DOM: */
    "lib": ["es2023"],
  },
}
rugged tapir
#

And do you have type: module in your package.json?

acoustic glen
#

No, I do not have any type:

rugged tapir
#

You are using module: NodeNext, which tells TS to use the Node.js module system, and Node.js module system works like:

  • If you have type: module in your package.json, then it's ESM.
  • Otherwise, it's CJS.
#

That's why your code is being compiled to CJS.

acoustic glen
#

This worked.