microsoft / microsoft/TypeScript

Cannot export both types and values from CJS

Open
#60,852 2 comments 1 reaction 1 assignee View on GitHub

@andrewbranch is already working on this.

Since Jan 3, 2025.

In Discussion Suggestion
Dominant language
Go
Stars
111k
Forks
14.3k
Avg merge
2d 4h
Merged PRs (30d)
132

Description

🔎 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 };

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.