Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't the exports field of npm work in typescript?

Our library @ltonetwork/lto, is written in typescript. We use tsc to compile to javascript in the lib folder.

The package contains several sub-packages, which are located in subfolders that contain an index.ts file.

When trying to import a submodule, like this

import {Transfer} from "@ltonetwork/lto/transactions";

I'm expecting this to work, but I get the following error

test.ts:1:24 - error TS2307: Cannot find module '@ltonetwork/lto/transactions' or its corresponding type declarations.

The package.json of @ltonetwork/lto contains

{
  "scripts": {
    "compile": "tsc -p ./tsconfig.json"
  },
  "main": "lib",
  "exports": {
    ".": "./lib/index.js",
    "./*": "./lib/*/index.js",
    "./package.json": "./package.json"
  },
  "files": [
    "lib",
    "interfaces.d.ts"
  ]
}

and the tsconfig.json is

{
  "compilerOptions": {
    "alwaysStrict": true,
    "baseUrl": "",
    "lib": ["es2017.object", "es2015", "es6", "dom"],
    "module": "commonjs",
    "sourceMap": true,
    "declaration": true,
    "target": "es6",
    "paths": {},
    "rootDir": "src",
    "outDir": "lib"
  },
  "include": ["src"]
}

I've tried to explicitly name the submodules, instead of using wildcards in exports, but that made no difference.

What am I doing wrong that's causing this import issue?


Edit: This is not related to monorepos or yarn workspaces. This is about using the exports field in npm with typescript 4.7.1-rc. This feature wasn't working with earlier versions of typescript.

For more information see https://github.com/microsoft/TypeScript/issues/33079

I've also tried

{
  "scripts": {
    "compile": "tsc -p ./tsconfig.json"
  },
  "main": "lib",
  "exports": {
    ".": {
      "require": {
        "default": "./lib/index.js",
        "types": "./lib/index.d.ts"
      },
      "import": {
        "default": "./lib/index.js",
        "types": "./lib/index.d.ts"
      }
    },
    "./transactions": {
      "require": {
        "default": "./lib/transactions/index.js",
        "types": "./lib/transactions/index.d.ts"
      },
      "import": {
        "default": "./lib/transactions/index.js",
        "types": "./lib/transactions/index.d.ts"
      }
    },
    "./package.json": "./package.json"
  },
  "files": [
    "lib",
    "interfaces.d.ts"
  ]
}
like image 211
Arnold Daniels Avatar asked Dec 02 '25 12:12

Arnold Daniels


2 Answers

Ensure moduleResolution in the consuming library is set to either Node16 or NodeNext in your tsconfig.json file.

Edit: bundler is now also an option.

like image 141
Rebecca Stevens Avatar answered Dec 04 '25 01:12

Rebecca Stevens


Since Typescript 3.1 we've been able to do this and it doesn't require the consumer to have a tsconfig.json.

"typesVersions": {
    "*": {
        "path1": [ "./path/to/path1.d.ts" ],
        "path2": [ "./path/to/path2.d.ts" ],        
    }
},

This may only work with named submodules.

like image 31
JakeDK Avatar answered Dec 04 '25 02:12

JakeDK



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!