Skip to content

Package cannot be imported for certain TypeScript configurations #604

Closed
@nwalters512

Description

@nwalters512

Describe the bug

I apologize in advance for filing this; ESM/CJS/TypeScript compatibility is a horrific can of worms.

Importing this package in a TypeScript project that uses "module": "Node16" fails when the project itself is not configured to use ESM (that is, package.json does not contain "type": "module").

I've created a reproduction here: https://github.com/nwalters512/sql-formatter-typescript-repro. Instructions are in the readme.

Expected behavior

Given that sql-formatter provides both ESM and CJS implementations, I would expect to be able to import the CJS version in this situation.

Actual behavior

TypeScript produces the following error:

src/index.ts:1:24 - error TS1479: The current file is a CommonJS module whose imports will produce 'require' calls; however, the referenced file is an ECMAScript module and cannot be imported with 'require'. Consider writing a dynamic 'import("sql-formatter")' call instead.
  To convert this file to an ECMAScript module, change its file extension to '.mts', or add the field `"type": "module"` to '/Users/nathan/git/sql-formatter-typescript-repro/package.json'.

1 import { format } from 'sql-formatter';
                         ~~~~~~~~~~~~~~~


Found 1 error in src/index.ts:1

Note that things still work correctly at runtime; the presence of the types field combined with "type": "module" in this package confused TypeScript enough that it doesn't realize that there is a completely valid CJS implementation. I considered filing an issue upstream on TypeScript itself, but this was already discussed on microsoft/TypeScript#54263, which was closed without any indication that TypeScript itself would fix this (even though I think they should).

I believe the way to fix this would be to drop the "types" field from "exports" and instead place *.d.ts/*.d.cts files adjacent to the files that are referenced by the "import" and "require" exports in package.json. This way, TypeScript will automatically discover the correct types based on the particular conditions that it's using to resolve the implementation files.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions