Skip to content

Cannot export both types and values from CJS #60852

Open
@kirkwaiblinger

Description

@kirkwaiblinger

🔎 Search Terms

verbatimModuleSyntax, commonjs, require, export, export type,

🕗 Version & Regression Information

⏯ Playground Link

https://www.typescriptlang.org/play/?moduleResolution=99&target=99&module=199&verbatimModuleSyntax=true&ts=5.8.0-dev.20241225#code/KYDwDg9gTgLgBDAnmYcBiEJwLxwM4xQCWAdgOZwA+cJArgLYBGwUA3AFDsDGANgIZ48cAEJ8ocAN4BfTqEiwcIsayA

💻 Code

I wanted to convert a *.ts file that gets interpreted as CJS (due to package.json "type" field) to use verbatimModuleSyntax for explicitness.

The file previously looked like this

// index.ts
export type Foo = string | number;
export const Bar = 42;

and could be imported like so

// foo.ts
import { type Foo, Bar } from './index';

const x: Foo = 42;
const y = Bar;

After enabling verbatimModuleSyntax, it seems no longer possible to export both Foo and Bar from index.ts. Some attempts:

type Foo = string | number;
const Bar = 42;

export = { Foo, Bar }; // error; Foo is a type but used as a value

This is ok,

export type Foo = string | number;
const Bar = 42;

but this is not

export type Foo = string | number;
const Bar = 42;
export = { Bar }; // An export assignment cannot be used in a module with other exported elements. (TS2309)

nor this

type Foo = string | number;
const Bar = 42;
export type { Foo };
export = { Bar }; // An export assignment cannot be used in a module with other exported elements. (TS2309)

tsconfig:

{
    "compilerOptions": {
        "verbatimModuleSyntax": true,
        "target": "ESNext",
        "module": "NodeNext",
        "strict": true,
    }
}

package.json: has "type": "commonjs"

🙁 Actual behavior

Can't find a way to export both types and values using CJS import/export syntax required by verbatimModuleSyntax

🙂 Expected behavior

There is a way to export both types and values using CJS import/export syntax

Additional information about the issue

Perhaps this is possible, and if so I'd ask it be added to the documentation. Without this, a currently-functioning CJS module cannot straightforwardly be converted to use verbatimModuleSyntax.

FWIW, if it's not possible, I don't see why at least one of the following wouldn't be allowed (specifically due to the use of export type to ensure only one value export exists)

export type Foo = string | number;
const Bar = 42;
export = { Bar }; // not a problem; only one value export

or

type Foo = string | number;
const Bar = 42;
export type { Foo };
export = { Bar };

Metadata

Metadata

Assignees

Labels

In DiscussionNot yet reached consensusSuggestionAn idea for TypeScript

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions