Skip to content

Declarations are unexpectedly used from node_modules in parent directory #30124

Closed

Description

TypeScript Version: 3.4.0-dev.20190227
Search Terms: nested node_modules module resolution

I have a project nested inside another project. Both package.jsons import the same library, but they are two different versions of the library.

Issue
In the files inside the inner project, I am able to import something that is only exported by the version of the library used by the outer project. When I open just the inner project in VSCode, I see two entries in the import intellisense for each export from the shared library, one from each version. It appears that Typescript is recursing up the directory tree, looking for node_modules and merging their declarations even through the library is already installed in the local node_modules.

Code

Here's the import that should fail. I should only be able to import from "fp-ts/lib/HKT" here:

https://github.com/leemhenson/fp-ts-oom-repro/blob/master/subproject/user.ts#L2

Here's the inner project's import of the library:

https://github.com/leemhenson/fp-ts-oom-repro/blob/master/subproject/package.json#L7

Here's the outer project's import of the library:

https://github.com/leemhenson/fp-ts-oom-repro/blob/master/package.json#L8

I've tried settings types: [] and typeRoots, exclude: ["../node_modules"] etc.

Related
#11994
#11363
#11257

Activity

  1. j-oliveras commented on Feb 27, 2019

    @j-oliveras
    Contributor

    Did you tried using Path mapping? Be aware that will not rewrite your imports.

  2. leemhenson commented on Feb 27, 2019

    @leemhenson
    Author
        "paths": {
          "fp-ts/lib/*": ["./node_modules/fp-ts/lib/*"]
        },

    and variants have no effect.

  3. InputNeuron commented on Apr 30, 2019

    @InputNeuron

    I have the same problem. what I think is happening is that:

    node_modules/typescript/lib/typesMap.json

    has an entry for 'md5' (and other things) and it's using the parent mode_modules for resolving it.

    I then get a ton of other associated errors due to module differences.

    I tried changing typeRoots, exclude, and paths and none of them work. The documentation is incorrect that parent directories will not be used.

    The only work around I've found is to move the parent node_modules out of the way.

    The root cause is that typescript tries to pull it's own things in which I didn't specify and there's no way to disable this or tell it to not load from ../node_modules

  4. InputNeuron commented on Apr 30, 2019

    @InputNeuron

    I also need to note that moving the node_modules temporarily out of the way is a really bad work around as it causes IntelliJ to go to 100% and needs to re-index all my modules for every build.

  5. InputNeuron commented on Apr 30, 2019

    @InputNeuron

    Also, an sub -project with only one .ts file (empty) still generates errors as typescript tries to load modules in its type map from the ../node_modules

  6. julkwiec commented on Jun 4, 2019

    @julkwiec

    I have exactly the same issue as @burtonator and Lee Henson (@leemhenson). Tried every possible combination of compilerOptions.typeRoots and compilerOptions.types, but the TS compiler keeps including ../../node_modules/@types no matter what I do.

  7. kvedantmahajan commented on Jun 16, 2019

    @kvedantmahajan
     "compilerOptions": {
           "types" : []
       }
    

    Will do the job.

  8. akomm commented on Jan 10, 2020

    @akomm
     "compilerOptions": {
           "types" : []
       }
    

    Will do the job.

    Will not do the job (fully). You should read documentation for typeRoots and types. It only works for global modules, not imported. For imported modules, you have to use paths and baseUrl.

    Either the docs are not correct, I did not understand them, or there is bug, because using it does not seem to restrict module resolution.

    I have the following set in an inner project's tsconfig.json:

    {
      "compilerOptions": {
        "strict": true,
        "target": "es5",
        "module": "commonjs",
        "moduleResolution": "node",
        "lib": ["dom", "es2017"],
        "jsx": "react",
        "typeRoots": ["./node_modules/@types"],
        "baseUrl": ".",
        "paths": {
          "*": ["./node_modules/*"]
        }
      },
      "include": ["src"]
    }

    Packages from parent/node_modules are still resolved.

    Used typescript 3.7.4.

  9. kvedantmahajan commented on Jan 20, 2020

    @kvedantmahajan

    Lee Henson (@leemhenson) I should have elaborated my answer a bit more because the setup also matters. I commented because I had a similar setup. So please evaluate yourself for this.

    First of all, I use yarn workspaces. What yarn as a package manager does is to hoist the packages automatically to the root. Thus, maintaining a central version for all sub-projects. So a sub-project doesn't only fetch from the parent. npm does a similar thing by --hoist flag but I have little experience in production setups.

    Second, if for some reason you do have a separate version of the same library for one sub-project then you SHOULD see two entries in IntelliSense.

    Third, if out of all the bad initial setups and to quickly calm down two entries to one, my earlier answer will do the work. How?

     "compilerOptions": {
           "types" : []
       }
    

    If you specify the above inside a sub-project's tsconfig.json, then you are basically stating explicitly that "Hey! I'm in charge of specifying types package(s)". In this case, I specify empty array which means typescript compiler will suppress any types from this particular sub-project.

    Andriy Komm (@akomm) pay attention

    More from Typescript documentation -

    A types package is a folder with a file called index.d.ts or a folder with a package.json that has a types field.

    Specify "types": [] to disable automatic inclusion of Types (@types) packages.

  10. akomm commented on Jan 20, 2020

    @akomm

    kushalmahajan
    Thanks for elaborating the answer so others understand when it fixes their problems and when not :)

    There is however no reason to quote me the docs, I recommended to check, because elaborating the "it does the job"-answer thrown at an issue is not going to retrospectively make the answer valid.

    Specifically the part following the quote is important.

  11. kvedantmahajan commented on Jan 20, 2020

    @kvedantmahajan

    Andriy Komm (@akomm) My purpose to quote you is obvious since you quoted me in the thread and mentioned something which is not a fact.

    Please do read my replies and official docs again. I would not mind replying to objectivity.

  12. akomm commented on Jan 20, 2020

    @akomm

    I am not going to continue this pedantic back and forth, one last time...

    Quote, this issue opening comment:
    #30124 (comment)
    I've tried settings types: [] and typeRoots, exclude: ["../node_modules"] etc.
    You did not pay attention to it.

    Quote, another comment from this issue:
    #30124 (comment)
    I have exactly the same issue as burtonator and leemhenson. Tried every possible combination of compilerOptions.typeRoots and compilerOptions.types, but the TS compiler keeps including ../../node_modules/@types no matter what I do.
    You did not pay attention to it.

    Your reply on this:

     "compilerOptions": {
           "types" : []
       }
    

    Will do the job.

    I stated, that this is incorrect (plus explanation).

    You retrospectively particularized your statement turning it from a broad solution to a specific solution. This does not make your (still unchanged) reply valid and my answer to it invalid.

    My last comment on this...

  13. 9 remaining items

  14. rbuckton commented on Nov 4, 2020

    @rbuckton
    Contributor

    While I can understand not wanting types from a parent node_modules folder to show up in a subproject when there are conflicts, our behavior is mimicking Node's resolution behavior:

    Welcome to Node.js v14.7.0.
    Type ".help" for more information.
    > process.cwd()
    'D:\\dev\\scratch\\fp-ts-oom-repro\\subproject'
    > require.resolve("fp-ts/lib/Either")
    'D:\\dev\\scratch\\fp-ts-oom-repro\\subproject\\node_modules\\fp-ts\\lib\\Either.js'
    > require.resolve("fp-ts/lib/HKTv14_1")
    'D:\\dev\\scratch\\fp-ts-oom-repro\\node_modules\\fp-ts\\lib\\HKTv14_1.js'
    > require("fp-ts/lib/HKTv14_1")
    {}
    >
    

    As far as I can tell, this behavior is the correct behavior and is not a bug.

  15. added
    Working as IntendedThe behavior described is the intended behavior; this is not a bug
    and removed
    Needs InvestigationThis issue needs a team member to investigate its status.
    RescheduledThis issue was previously scheduled to an earlier milestone
    on Nov 4, 2020
  16. akomm commented on Nov 5, 2020

    @akomm

    Ron Buckton (@rbuckton) If I understand Lee Henson (@leemhenson) correct, his issue is that the types package is found locally, but the types from parent node_modules is still used and merged. AFAIK node's behavior is to only go up, when package has not been found locally.

  17. rbuckton commented on Nov 5, 2020

    @rbuckton
    Contributor

    My comment was intended to serve as proof that node still navigates up when a part of a package sub-directory isn't found.

  18. laurent22 commented on Jan 5, 2023

    @laurent22

    My comment was intended to serve as proof that node still navigates up when a part of a package sub-directory isn't found.

    I don't know what Node is doing, but what TypeScript is doing doesn't seem right. In my case it's trying to parse type files and fails with errors like this:

    ERROR in /packages/app-cli/node_modules/@types/jest/index.d.ts
    [tsl] ERROR in /packages/app-cli/node_modules/@types/jest/index.d.ts(462,62)
          TS1005: ']' expected.
    
    ERROR in /packages/app-cli/node_modules/@types/jest/index.d.ts
    [tsl] ERROR in /packages/app-cli/node_modules/@types/jest/index.d.ts(462,65)
          TS1005: ';' expected.
    

    I can't make any sense of these errors, but more importantly why should I care that TypeScript can't parse files that aren't even used by my project? If I move said project to a different place with no parent node_modules, it works just fine.

    Assuming this is, anyway, the right way to load packages (also it feels very wrong), at least there should be a clear options to disable this behaviour.

  19. rbuckton commented on Jan 5, 2023

    @rbuckton
    Contributor

    These errors look to be coming from a third-party tool (tsl?), not TypeScript.

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

Metadata

Metadata

Labels

Working as IntendedThe behavior described is the intended behavior; this is not a bug

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions