Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for NodeJS 12.7+ package exports #33079

Closed
rbuckton opened this issue Aug 26, 2019 · 203 comments
Closed

Support for NodeJS 12.7+ package exports #33079

rbuckton opened this issue Aug 26, 2019 · 203 comments
Labels
Committed The team has roadmapped this issue Domain: ES Modules The issue relates to import/export style module behavior Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. Suggestion An idea for TypeScript

Comments

@rbuckton
Copy link
Member

NodeJS 12.7 added support for a (currently experimental) feature for custom package imports and exports in package.json: https://github.com/jkrems/proposal-pkg-exports/

In short, this feature allows a package author to redirect exports in their package to alternate locations:

{
  "name": "pkg",
  /* [...] */
  "exports": {
    "./foo": "./target.js",
    "./bar/": "./dist/nested/dir/"
  }
}

This is currently only available when --experiemental-exports is passed to NodeJS, however we should continue to track the development of this feature as it progresses.

@rbuckton rbuckton added the feature-request A request for a new feature label Aug 26, 2019
@rbuckton
Copy link
Member Author

CC: @weswigham, @DanielRosenwasser

@weswigham
Copy link
Member

Yeah, I know - I don't think we should implement support for it till it's stabilized - things like how . works are still being discussed in the modules group.

@rbuckton
Copy link
Member Author

I agree, this issue exists primarily to serve as a place for us to track the progress of this feature in NodeJS.

@richturner
Copy link

Given node is now at v12.11.1 and I believe v12 will enter LTS soon has this functionality stabilised enough to warrant inclusion in typescript module resolution now?

This will prove very helpful when working with yarn simlinked monorepos as the existing types field isn't enough when there are multiple files not in the package root dir.

@weswigham
Copy link
Member

We spoke about it in the modules wg on Wednesday - it's going to unflag with es modules as a whole (even the cjs support), so it can be a reliable fallback-allowing mechanism for pre-esm node. It... Should... Unflag during the node 12 lifetime. But that hasn't happened yet, and details are still being fleshed out~

@jgoz
Copy link

jgoz commented Nov 22, 2019

Looks like this has unflagged in 13.2.0: https://github.com/nodejs/node/blob/v13.2.0/doc/changelogs/CHANGELOG_V13.md#notable-changes

(with support for exports)

@jonaskello
Copy link

Node 14 (next LTS) is scheduled for release 2020-04-21 and I'm guessing it will support exports unflagged as node 13 does and at that point I know I will want to use it :-). Is typescript planning to support exports in the same timeframe as the node 14 release?

@weswigham
Copy link
Member

Yeah, we've just been waiting for it to stabilize a bit, since it's still experimental, even if it's unflagged (it emits a warning when it's used in resolution), since we don't want to need to support an old experimental version and a final version (and it does still see significant change - there's discussion about removing the main fallback right now).

@okdecm
Copy link

okdecm commented Mar 8, 2020

Is there a way around this for the time being? Perhaps manually linking up modules via an index.d.ts?

I'm using path based modules such as @okdecm/my-package/Databases/Postgres and thus have no index to specify as my main.
The code now works using the exports option, but tooling such as Visual Studio Code still can't resolve the modules for referencing (due to current lack of TypeScript support).

It'd be ideal if there were a way to explicitly set these in the mean time.

@sparebytes
Copy link

sparebytes commented Mar 8, 2020

@okdecm, try setting the baseUrl and paths. If @my/bar depends on @my/foo then you might have a tsconfig like this:

// packages/bar/tsconfig.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "rootDir": "src",
    "outDir": "dist/lib",
    "composite": true,
    "paths": {
      "@my/foo": [
        "../foo/dist/lib/index"
      ],
      "@my/foo/models": [
        "../foo/dist/lib/a/b/c/d/models"
      ],
      "@my/foo/*": [
        "../foo/dist/lib/*"
      ]
    }
  },
  "references": [{ "path": "../foo/tsconfig.json" }]
}

The paths should point to the emitted file. Remember that the paths are relative to the baseUrl so it might make sense to set the baseUrl a parent folder.

@jkrems
Copy link

jkrems commented Mar 13, 2020

One of the ideas for conditional exports was to allow things like types per exported path.

{
  "name": "pkg",
  /* [...] */
  "exports": {
    "./foo": {
      "types": "./types/foo.d.ts",
      "default": "./target.js"
    },
    "./bar/": {
      "types": "./types/bar.d.ts",
      "default": "./dist/nested/dir/"
    }
  }
}

This would be great to see in a potential TypeScript integration. :)

@jarodburchill
Copy link

Any updates on this?

@lukeed
Copy link

lukeed commented Jun 20, 2020

I'm not sure I understand what the obstacle is? I would think that TS just needs to continue looking at the types/typings field, and load it as is. It should up to the author to declare multiple module definitions within that single d.ts file. Important TS fields/paths should not be scattered throughout the package.json file – too much room for error.

I have examples of this already. I'd expect these to Just Work ™️ :

This would be backwards compatible too, because a definition file that doesn't contain a declare module wrapper already assumes that the definition is the default / applies to the entire package.

@lukeed
Copy link

lukeed commented Jun 20, 2020

An interesting tidbit is that if you load use a submodule inside a JS file, eg kleur/colors, within VSCode, the submodule's types are picked up and inferred correctly. Writing the same code inside a .ts file short circuits everything to any type.

import * as colors from 'kleur/colors';

colors.r
// (js) has code completions
// (ts) *crickets*

@mh-alahdadian
Copy link

this exports field is stable in node api now
so it's the time to ts support it
any update?

@weswigham
Copy link
Member

Sort-of. Basic usecases are pretty stable, but a lot of conditional-related cases are still under discussion. Anyways, we've missed the mark for inclusion in 4.0, so 4.1 would be the earliest you'd see it.

@ghost
Copy link

ghost commented Sep 12, 2022

Is there any update on this?

@haf
Copy link

haf commented Sep 15, 2022

@andrewbranch I'm curious; what problem do you have understanding what the bug is? @Mitsunee made it very clear that he expects TypeScript to follow package.json's exports declarations. I've tried finding exactly what tsconfig you're on about, but I suppose it's compilerOptions.moduleResolution which can be set to node (see docs). In this case you'd expect it to do what it says on the tin (NodeJS docs).

If you follow any of the above referenced issues you'll find many examples, beyond what @Mitsunee already posted screenshots of.

Here's another screenshot for your benefit:

bild

in this case, I expect not to have this error message in consuming code:

bild

In summary, TS should honour the package resolution mechanism. This is especially important if you ever expect modules to start moving from CommonJS to ECMAScript modules.

It seems work has been done to support this; so for anyone finding this, even if you're on node14, you might be able to use node16 as the target in tsconfig.json. Also, a 1:1 mapping between paths seems to work in TS <4.7.

@Mitsunee
Copy link

Please cease mentioning me in this ticket. I've been told off from using this bug tracker because I'm "causing email spam", so please don't cause me email spam. There is clearly no interest in fixing type imports for libraries and I've found an (admittedly stupid and annoying) workaround that has been working for me.

@andrewbranch
Copy link
Member

I've been told off from using this bug tracker because I'm "causing email spam"

I hope it’s clear to everyone that the person who said this is a random community member completely unaffiliated with this project and doesn’t speak for Microsoft or TypeScript. Anyone with on-topic comments is always welcome to participate, and anyone who implies otherwise should be ignored.

That said, this issue is closed and the conversation has not been very productive for some time. I have opened #50794 to track adding support for package.json exports outside of Node. I had been tracking it as part of #50152, but recent comments clearly indicate that not everyone is willing to read it, which is fair (it’s pretty long).

I hate locking issues, so I’m not going to do that here just yet, but I can’t imagine how any further discussion here can be productive:

  • If you think you have a bug, open a new issue.
  • If you have a question about current features, ask StackOverflow or Discord.
  • If you want to discuss package.json exports outside of Node, go to Support package.json exports outside of Node #50794.
  • If you want to discuss module resolution outside of Node in general, go to A Proposal For Module Resolution #50152.
  • If you want to express your discontent, trust me, I already get it. But tweet at me @atcb if you need to, I guess.
  • If you want to know if there are “any updates on this,” read the thread.

Please don’t make me lock this ❤️

DarrenDanielDay added a commit to DarrenDanielDay/func-di that referenced this issue Sep 22, 2022
@hacknlove
Copy link

[tsconfig.json].compulerOptions.moduleResolution = "node16" has worked for me flawlessly.

I have npm workspaces, each workspace exporting different modules with [package.json].exports

I was unable to import a module from a different workspace, until I changed module Resolution to node16.

mristin added a commit to aas-core-works/aas-core3.0rc02-typescript that referenced this issue Dec 21, 2022
We do not set the `exports` in `package.json` as it seems to be not
stable yet (see [this issue in TypeScript], for example). Therefore, we
import the main module (`index.js`) and re-write the examples
accordingly.

[this issue in TypeScript]: microsoft/TypeScript#33079
mristin added a commit to aas-core-works/aas-core3.0rc02-typescript that referenced this issue Dec 21, 2022
We do not set the `exports` in `package.json` as it seems to be not
stable yet (see [this issue in TypeScript], for example). Therefore, we
import the main module (`index.js`) and re-write the examples
accordingly.

[this issue in TypeScript]: microsoft/TypeScript#33079
@btakita
Copy link

btakita commented Feb 10, 2023

I'm confused over this conversation. I'm using vite & a pnpm monorepo with *.ts files that are automatically transpiled with vite/esbuild. Is something like this possible? I would rather keep my app files in *.ts instead of using *.js/*.d.ts

{
  "name": "my-package",
  "exports": {
    "./ui": "./src/ui/index.ts"
  }
}

or

{
  "name": "my-package",
  "exports": {
    "./ui": {
      "types": "./src/ui/index.ts",
      "default": "./src/ui/index.ts"
    }
  }
}

@shubhamdhingra007
Copy link

Please cease mentioning me in this ticket. I've been told off from using this bug tracker because I'm "causing email spam", so please don't cause me email spam. There is clearly no interest in fixing type imports for libraries and I've found an (admittedly stupid and annoying) workaround that has been working for me.

@Mitsunee, can you tell about your workaround please?

@microsoft microsoft locked as resolved and limited conversation to collaborators Apr 21, 2023
@RyanCavanaugh
Copy link
Member

RyanCavanaugh commented Apr 21, 2023

I think we'll draw the line at "@-ing people who explicitly asked not to be @-ed"

+1 to #33079 (comment)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Committed The team has roadmapped this issue Domain: ES Modules The issue relates to import/export style module behavior Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests