Skip to content

Self-referencing a package using its name #38675

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

Closed
5 tasks done
BTOdell opened this issue May 20, 2020 · 6 comments
Closed
5 tasks done

Self-referencing a package using its name #38675

BTOdell opened this issue May 20, 2020 · 6 comments
Labels
Revisit An issue worth coming back to Suggestion An idea for TypeScript

Comments

@BTOdell
Copy link

BTOdell commented May 20, 2020

Search Terms

Self reference package name node exports

Suggestion

The Node.js documentation for ECMAScript Modules specifies that you should be able to self-reference the package that the module is in by the package's name:
https://nodejs.org/api/esm.html#esm_self_referencing_a_package_using_its_name
https://nodejs.org/api/packages.html#packages_self_referencing_a_package_using_its_name

I know this feature is still considered experimental by Node, but I think TypeScript should support this behavior in their Node-style module resolution algorithm.
No longer experimental as of Node.js v13.6.0

Use Cases

This is helpful for writing tests that reference the package instead of directly to the files.
That way you can also test that your package.json is in the correct format to allow your package to be consumed by ES modules and CommonJS code.

There is a work-around available that involves symlinking your project into the project's own node_modules.

You can do this by executing:
npm link && npm link foo
(where foo is the name of your package)

OR

You can use a library like install-self: https://www.npmjs.com/package/install-self

It would be nice if you didn't have to perform these extra steps or install extra dev dependencies.

Examples

I ran into this issue when I was trying to do the following:
https://github.com/BTOdell/unknown/blob/719727457ad1dca745789d05bcbb1ba98c7a78e4/test/unknown.spec.ts

Even though TypeScript fails to compile, it still emits the correct JavaScript and I can run it on Node.js v14 without errors.

Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.
@RyanCavanaugh RyanCavanaugh added Revisit An issue worth coming back to Suggestion An idea for TypeScript labels Jun 9, 2020
@BTOdell
Copy link
Author

BTOdell commented Jul 20, 2021

Can this feature be revisited now? This functionality in Node.js has been out for several major releases and it's time the Node module resolution algorithm in TypeScript was updated.

@BTOdell
Copy link
Author

BTOdell commented Oct 3, 2021

Happy to see that this has finally been implemented in TypeScript 4.5 Beta:
https://devblogs.microsoft.com/typescript/announcing-typescript-4-5-beta/

Make sure to set the module to node12 in your tsconfig.json to use self-referencing imports.
🎉🎉🎉

@Offirmo
Copy link

Offirmo commented Apr 28, 2022

[edit: this was already reported https://github.com//issues/46762]

I'm on TypeScript nightly 4.7.0-dev.20220427 and can't make it self-referencing work.

error
src/index_spec.ts:3:30 - error TS2307: Cannot find module '@offirmo-private/json-stable-stringify' or its corresponding type declarations.

package.json

{
	"name": "@offirmo-private/json-stable-stringify",
	"type": "module",
	"exports": {
		".": {
			"import": "./dist/src.es2021/index.js",
			"require": "./dist/src.es2021.cjs/index.js"
		}
	},

tsconfig.json

"module": "nodenext",
"moduleResolution": "nodenext",

From a unit test placed inside the module (sibling to index.ts):

import stable_stringify from '@offirmo-private/json-stable-stringify'

Technically the target file (dist/src.es2021/index.js) is not present yet since Typescript is in the process of building it, but that's a normal setup.

Any idea of what I'm doing wrong?

@eric-burel
Copy link

Hi, is this supposed to work in TS 4.6? I had a package that was referencing itself and I ended up with Cannot write file ... because it would overwrite input file when building twice, until I removed the self reference.

@mishabruml
Copy link

Hey, I'm experiencing the same issue as @Offirmo with a very similar setup

@WillsterJohnson
Copy link

WillsterJohnson commented May 28, 2022

Having a similar issue on 4.8.0-dev.20220528 (latest on @next at time of writing), 4.7.1-rc (latest @rc at time of writing), and on 4.7.2 (but only in transpiled JS).
However the problem only occurs on submodules, importing from package-name works fine but package-name/submodule does not. I've tried both ./submodule and submodule as keys for package.json exports, but no luck.

On 4.7.2 I tried npm linking the package to a different folder and importing from there, but it doesn't work for the module itself, let alone submodules.

exports field;

"exports": {
    ".": {
      "import": "./dist/esm/index.mjs",
      "require": "./dist/cjs/index.cjs",
      "types": "./dist/types/index.d.ts"
    },
    "./factory": { // tried both with and without `./`
      "import": "./dist/esm/factory.mjs",
      "require": "./dist/cjs/factory.cjs",
      "types": "./dist/types/factory.d.ts"
    }
  }

No idea what's going wrong, and I doubt it helps that I'm new to this side of Node.js

Edit: I'm running tsc 3 times for each subdir of ./dist, then running a script to rename js files to mjs or cjs, I'm not trying to reference .js via .cjs or .mjs, those are the real extensions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Revisit An issue worth coming back to Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

6 participants