Skip to content

change package.json entry point and duplicate declaration #32

@spiltbeans

Description

@spiltbeans

Background

In TypeScript 4.7 it was recommended to export your package with a conditional nested export map such as:

// package.json
{
    "name": "my-package",
    "type": "module",
    "exports": {
        ".": {
            // Entry-point for `import "my-package"` in ESM
            "import": {
                // Where TypeScript will look.
                "types": "./types/esm/index.d.ts",
                // Where Node.js will look.
                "default": "./esm/index.js"
            },
            // Entry-point for `require("my-package") in CJS
            "require": {
                // Where TypeScript will look.
                "types": "./types/commonjs/index.d.cts",
                // Where Node.js will look.
                "default": "./commonjs/index.cjs"
            },
        }
    },
    // Fall-back for older versions of TypeScript
    "types": "./types/index.d.ts",
    // CJS fall-back for older versions of Node.js
    "main": "./commonjs/index.cjs"
}

This was recommended multiple times:


Problem

The supposed reason is if a user consumes your package with a single shared .d.ts and has TypeScript, it might be like "oh ok this package only has ESM" or vice-versa.

The following explanation was hosted on the domain https://www.typescriptlang.org/docs/handbook/esm-node.html:

It’s important to note that the CommonJS entrypoint and the ES module entrypoint each needs its own declaration file, even if the contents are the same between them. Every declaration file is interpreted either as a CommonJS module or as an ES module, based on its file extension and the "type" field of the package.json, and this detected module kind must match the module kind that Node will detect for the corresponding JavaScript file for type checking to be correct. Attempting to use a single .d.ts file to type both an ES module entrypoint and a CommonJS entrypoint will cause TypeScript to think only one of those entrypoints exists, causing compiler errors for users of the package.

In October 2023 the following module documentation was published microsoft/TypeScript-Website#2946

In the above PR the domain explaining why you shouldn't share a single .d.ts file was deleted. This explanation now only exists in the TypeScript 4.7 release notes


Resolution

Because it's unclear if users will face this issue, the following resolution should be done to accommodate users consuming this package with an older version of TypeScript should they encounter this issue:

  • change package.json to comply with multiple type files
  • change bundle step to include duplicate .d.ts files

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions