TypeScript package with multiple entry points
Asked Answered
A

2

18

The standard way to expose node package modules is to list them in the index.ts, like so:

export * from './module1';
export * from './module2';

However, this loads the content of both modules immediately. I want to have a module that is not exported in the index.ts file, as it requires some optional dependencies to be installed.

I followed this guide: https://blog.mozilla.org/data/2021/04/07/this-week-in-glean-publishing-glean-js/

My package.json:

  "exports": {
    ".": {
      "import": "./dist/es/index.js",
      "require": "./dist/cjs/index.js"
    },
    "./module2": {
      "import": "./dist/es/module2.js",
      "require": "./dist/cjs/module2.js"
    }
  },
  "typesVersions": {
    "*": {
      ".": [
        "./dist/types/index.d.ts"
      ],
      "./module2": [
        "./dist/types/module2.d.ts"
      ]
    }
  },
// fallback for older Node versions:
  "module": "dist/es/index.js",
  "main": "dist/cjs/index.js",
  "types": "dist/types/index.d.ts",

After I build the project (with tsc, separately for CJS and ESM) the output dir structure looks like this:

- dist
  - cjs
    - index.js
    - module2.js
  - es
    - index.js
    - module2.js
  - types
    - index.d.ts
    - module2.d.ts

However, when I publish this package and install it in the client project, module2 does not work.

import {sayHello} from 'ts-exports-test';
import {sayGoodbye} from 'ts-exports-test/module2';

console.log(sayHello());
console.log(sayGoodbye());

I run it with ts-node and I'm getting the error:

src/index.ts:2:26 - error TS2307: Cannot find module 'ts-exports-test/module2' or its corresponding type declarations.

Note: with clients using TS 4.5 the types paths can be declared in "exports" section, making the "typesVersions" hack unnecessary. But this is for the future.

Aesthetics answered 26/10, 2021 at 20:29 Comment(2)
I tried to reproduce the issue, but it's working for me. Could you check this repo and check if there is any difference with your configuration github.com/diedu89/ts-export-import-testApprentice
Thanks for trying to reproduce it. However, in your example, the ts-exports-test/module2 import in the client resolves to module2.ts file in the package main dir, not to dist/types/module2.d.ts (according to WebStorm). If you remove the source files from the output package by adding "files": ["dist"] to package.json or if you move the source files to src directory, it won't work.Aesthetics
A
25

It works if you define the paths in typesVersions like this:

  "typesVersions": {
    "*": {
      "*": [
        "dist/types/index.d.ts"
      ],
      "module2": [
        "dist/types/module2.d.ts"
      ]
    }
  }

Not sure what convention does it follows, but it looks like paths like . or ./ are not valid.

You can check the repo https://github.com/diedu89/ts-export-import-test

Apprentice answered 31/10, 2021 at 22:17 Comment(0)
C
12

2022, TypeScript 4.9 and beyond

exports is prioritized over typesVersions

Previously, TypeScript incorrectly prioritized the typesVersions field over the exports field when resolving through a package.json under --moduleResolution node16. If this change impacts your library, you may need to add types@ version selectors in your package.json’s exports field. The proper way to do this is using exports field now -

{
      "type": "module",
      "exports": {
          ".": {
              "import": "./dist/es/index.js",
              "require": "./dist/cjs/index.js",
              "types": "./dist/types/index.d.ts"  ✅
          },
          "module2" {
              "import": "./dist/es/module2.js",
              "require": "./dist/cjs/index.js",
              "types": "./dist/types/module2.ts"  ✅
          }
      }
  }
Crossbeam answered 14/3, 2023 at 22:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.