16

I have a Typescript-based project with multiple .d.ts files that I want to export as npm package and use in another project.

In that other project, I want to be able to call:

import {Foo} from "@my-company/project-name/x/y/Foo"

My project structure looks like:

<project_root>
|_ node_modules
|_ src
|  |_ x
|     |_ y
|     |  |_ Foo.ts
|     |_ Bar.ts
|_ package.json
|_ tsconfig.json

My tsconfig.json file:

{
  "compilerOptions": {
    "module": "es2015",
    "esModuleInterop": true,
    "target": "es6",
    "moduleResolution": "node",
    "sourceMap": true,
    "outDir": "dist",
    "declaration": true
  },
  "lib": ["es2015"],
  "include": [
    "src"
  ],
  "exclude": [
    "node_modules"
  ]
}

The result of running tsc is that a dist folder is created containing the d.ts files and the .js files. When running npm pack, I end up with a .tgz file containing the following structure.

Note that it includes the dist folder in the directory structure.

package
 |_ dist
 |  |_...
 |_ package.json

The result is that I can't write

import {Foo} from "@my-company/project-name/x/y/Foo"

but have to write

import {Foo} from "@my-company/project-name/dist/x/y/Foo"

instead (note the extra dist in the path).

Based on the node documentation, I thought I could fix this by adding the following to my package.json file:

  "exports": {
    "./": "./dist/"
  }

but that seems to have no effect at all. The import cannot be found, unless I add the extra dist to the path.

I found a lot of other posts all with:

  • Solutions that look very complicated or are tied to a specific build system
  • Solutions that enforce special steps on the users of my package (like using compiler options)
  • Solutions/suggestions in closed Github issues (closed != fixed)
  • Old (over 2 internet years) posts, probably from before the exports option was available.

I would prefer to simply get that exports option to work. Anybody any idea what I am missing in my setup or doing wrong ? I am very new to the whole JS/TS/npm ecosystem so I think I might be overlooking something that is obvious to veterans.

For now, the workaround I found is to manually re-create the tgz file and remove the dist folder from the folder structure. But that feels far from perfect. For example npm install link_to_git_repo won't work.

Robin
  • 36,233
  • 5
  • 47
  • 99
  • Just an idea : can you write an index.js at the root of your project, and in this index.js, you import all your dist files, so when you import your package, you import your index.js which import and export all your function/classes from your dist folder ? – ocheriaf Sep 30 '19 at 08:27
  • 1
    That is an option, but it requires a lot of work (which perhaps can be automated). I was under the impression that with the `exports` option this was no longer necessary. Seeing as TS is rising in popularity, I would also hope that I am not the first person trying to solve this problem – Robin Sep 30 '19 at 09:02

2 Answers2

2

Configuring the typesVersions in the package.json fix this problem for me :

  "exports": {
    "./": "./dist/"
  },
  "typesVersions": {
    "*": {
      "*": ["./dist/*"]
    }
  },
jbdemonte
  • 667
  • 1
  • 7
  • 15
0

It doesn't appear to be possible using only package.json out of the box (see this issue on npm). A suggested workaround is to npm publish from the dist folder directly. This can be easily automated with a few scripts but it only works when publishing to npm, not when importing using git urls.

Renaud
  • 4,569
  • 7
  • 41
  • 72