FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Recommendation for exposing multiple TypeScript modules from single NPM package · Issue #8305 · microsoft/TypeScript · GitHub

Repository navigation

Recommendation for exposing multiple TypeScript modules from single NPM package #8305

Description

The module resolution logic in the handbook doesn't mention how nested modules are supported from a single npm package. There is an old issue discussing this that has been closed: #5804

Neither the solution here or simply trying to refer to modules beneath the root dir referred to by the typings or main path seems to work. Is there a documented best practice? The documentation says that ambient modules should not be used in the typings field in package.json.

Just to be clear, I want to write this in a consuming app:

import {stuff} from "my-npm-lib/submodule"

Where the package.json file in my-npm-lib has:

    "main": "lib/index.js",
    "typings": "lib/index.d.ts",

And the file structure in the my-npm-lib:

my-npm-lib\
    index.js
    index.d.ts
    submodule.js
    submodule.d.ts

Currently this complains with a module not found error. But this works, but shouldn't:

import {stuff} from "my-npm-lib/lib/submodule"

This is all with the module resolution setting set to node.

Activity

  1. mhegazy commented on Apr 26, 2016

    Contributor

    We need to add documentation, so leaving this issue open to track that, and marking it as such.

    For the question, the recommendation is to generate the .d.ts with 1:1 mapping to your .js files, and place them next to the .js file in the published package, as you mentioned. the "typings" field specify the main entry point, matching "main" for the .js file.

    I have a sample posted at https://github.com/mhegazy/npm-dependency-test, take a look and let me know if you have more questions.

  2. added
    QuestionAn issue which isn't directly actionable in code
    DocsThe issue relates to how you learn TypeScript
    @typesRelates to working with .d.ts files (declaration/definition files) from DefinitelyTyped
    on Apr 26, 2016
  3. joewood commented on Apr 26, 2016

    Author

    Thanks Mohamed Hegazy (@mhegazy)
    As I thought. The only real way of achieving submodules is to pollute the root directory. I think that's a limitation of JavaScript/npm too though, so not a massive deal.

    One option to avoid the pollution is to use a postinstall script to only pollute the root dir after npm install. This works fine, but it doesn't work too well with npm link. Another option could be to just move the build files from a distribution dir to the root in postinstall. Anyway, right now I've just resorted to adding a files.exclude filter in vscode to hide the mess.

    As you suggested, it would be great to update the handbook on best practices for distributing typescript built libraries, especially with respect to typings and dependent types.

  4. jcansdale commented on Jun 3, 2016

    Mohamed Hegazy (@mhegazy) I'm confused about why there is the need for a separate "typings" entry when the .d.ts is invariably next to the one referenced by "main". Why not simply look next to the "main" .js or at least look there as well?

  5. mhegazy commented on Jun 7, 2016

    Contributor

    Not sure i see the issue really. if you are adding "main" property in your package.json, should not be too much to ask to add "typings" as well.

  6. jcansdale commented on Jun 7, 2016

    Mohamed Hegazy (@mhegazy) It's more that is seems inconsistent. From my understanding, if you: import foo = require("foo.js"), TypeScript tools will automatically look for type definitions in "foo.d.ts". If however you: require("bar") and there is a "main": "foo.js" in bar/package.json, TypeScript tools won't automatically look for type definitions in "bar/foo.d.ts".

    This is a shame because otherwise you could convert a JavaScript package into TypeScript by simply renaming the .js files to .ts and compiling with the definitions option. Unfortunately you need to know about the "typings" option otherwise your consumers won't see your type definitions. It just seems like an unnecessary gotcha. Why not support "main" relative as well as "typings"?

    Does that make sense?

  7. mhegazy commented on Jun 9, 2016

    Contributor

    it does work for index.js -> index.d.ts. We could add support for main. but the idea was if you chose to change the defaults for your package by setting a main, then you should also consider what you want to put in typings, they may or may not be in the same place.

  8. jcansdale commented on Jun 9, 2016

    How about making it so that if typingsexists look for it there, otherwise look for it relative to main? Maybe there is one but I can't think of a good reason why you wouldn't want to look next to main if a typings entry doesn't exist. I'm thinking more for package authors who've written their package using TypeScript, rather than authors who want to add typings to their JavaScript package.

  9. mhegazy commented on Jun 9, 2016

    Contributor

    feel free to file a separate issue for this proposal.

  10. bogdanmanate commented on Jul 14, 2016

    This will definitely be a major improvement for Typescript development. I'm currently developing a library in TS and this library should be included in an Angular 2 application. I've also looked into angular repository to see how they are exporting the modules, but it seems that they bundle the modules in a single file.

  11. mhegazy commented on Jul 22, 2016

    Contributor

    here is the documentation for writing declaration files. please let us know if there are any missing scenarios.

  12. 24 remaining items

  13. mrmckeb commented on Jan 16, 2020

    If you have a small enough library, maybe that makes sense
    Correct, we have a library that is shared (internally) and it's quite big. We could export everything at root, but it would certainly be cleaner to have "submodules".

    I know we could also just separate these out into different packages as an alternative, but that complicates local development in our workflow.

  14. sweeetland commented on Mar 8, 2020

    Almost four years later and still no practical solution to this? 🤔

  15. tomsh99 commented on Mar 17, 2020

    Any solution for this frustrating problem?

  16. vankessel commented on Mar 19, 2020

    Ditto ☝️ Would be nice to be able to do this

  17. jaens commented on Mar 21, 2020

    This used to be a fundamental restriction of Node.js, but recently there's added support for the exports field in package.json which does allow this.

    TypeScript support is tracked in #33079.

  18. panva commented on Oct 2, 2020

    Any solution for this frustrating problem?

    #33079 (comment)

  19. slavafomin commented on Feb 17, 2021

    I've also spent a lot of time today trying to figure out why my declaration files are not loaded. I was compiling my declarations to the dist/types/*.d.ts directory. I was expecting TypeScript to be able to resolve type modules relative to the dist/types/index.d.ts file specified in package.json: "types": "dist/types/index.d.ts". However, it wasn't the case. I've tried to use the following option: "types": "dist/types/" to specify the root directory, but it wasn't working either.

    I guess it would be very reasonable to expect from TypeScript to look for declarations relative to the directiry/file specified in types property of package.json manifest.

    I can't quite comprehend why this issue is closed without a solution…

  20. Toliak commented on Mar 9, 2021

    Slava (@slavafomin), the same... I have reproduced this bug (I think it is disagreeable bug...) with rxjs@7.0.0-beta.12.
    There is "types" key in package.json
    However, auto import suggests nothing for example for pipe (and this variable is exported from index.d.ts)

    UPD: Well, I saw, that dev-dependencies are not being indexed on auto-suggesting. Thats the another issue. Maybe installing your package as dependency (not dev-dependency) will help you..

  21. tstewart-klaudhaus commented on May 18, 2021

    Thanks to Chris Krycho (@chriskrycho) for the very clear description of the situation and workaround in his article linked from #8305 (comment)

    The fact that the TS compiler cannot resolve submodule definitions that were generated and positioned within the package structure by the TS compiler itself is pretty remarkable. As a case of the TS compiler not being able to consume its own output, it could be viewed as an internal inconsistency.

    My use case is providing a submodule with interfaces intended to be augmented (merged) via ambient declaration. This is itself a workaround for TS lack of higher-kinded types. I get why the HKT thing is difficult, but this submodule resolution issue seems on the surface like it should be much more tractable.

  22. softmarshmallow commented on Jun 24, 2021

    I'm having same problem while using one package for both npm publication and for using as submodule package as my other typescript project.

    specifying main should point index.ts file and tsc or yarn/npm should somehow automatically link to dist/index.js

    or perhaps this should be another thread fro npm & package.json?

    This is a huge pain since we share a lot of project as submodule & for both npm in more thatn 100+ repos

  23. Stvad commented on Aug 28, 2022

    #33079 seems to be fixed, but I still can't find a great working example of a library with submodules hierarchy set up. Anyone has good references?

  24. ShaMan123 commented on Feb 3, 2023

    I have spent hours trying to configure a repo to work with submodule types. The repo has a build tool, rollup, and a folder structure that doesn't reflect the submodule importing scheme.

    #8305 (comment) has pointed out rxjs so I looked at the config they've done since they manage to expose typed submodules with a build tool and w/o mirroring the submodule importing scheme as suggested in the official guide.

    Related: #17945

    Findings

    It seems that though TS doesn't respect the exports.*.types field in package.json it does respect using typesVersions to specify submodule resolution strangely enough (e.g. fabricjs/fabric.js@b326dd6)
    I am not sure if this is enough on its own or if you need to define paths in tsconfig.json so I did that as well.
    I am sure that defining paths in tsconfig.json w/o the package.json config doesn't work (though I read it should).
    Also it seems relative paths are not recognized so use abs syntax that is relative to root.

    Hope this helps someone.
    TS if it works with typesVersions sounds like it can work with the exports.*.types field in package.json.

  25. locked as resolved and limited conversation to collaborators on Oct 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    @typesRelates to working with .d.ts files (declaration/definition files) from DefinitelyTypedDocsThe issue relates to how you learn TypeScriptQuestionAn issue which isn't directly actionable in code

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions


      Back | FazBrowse Home | New Git URL