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

TypeScript module versions conflicts #33137

Closed
imt-jaime opened this issue Aug 29, 2019 · 12 comments
Closed

TypeScript module versions conflicts #33137

imt-jaime opened this issue Aug 29, 2019 · 12 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@imt-jaime
Copy link

imt-jaime commented Aug 29, 2019

TypeScript Version: 3.4.0-dev.201xxxxx

Search Terms:

types conflict
modules conflict ts(2742)
duplicate modules
module versions conflict
monorepo modules conflict

Code

index.ts (main project)

import { moduleB } from 'ts-issue-module-b';
// import { SomeInterface } from 'ts-typelib-example'; // this line makes no sense

const valueB = moduleB(3); // <---- error ts(2742)

export {
  valueB
}

ts-module-b (linked package module)

import { SomeInterface } from 'ts-typelib-example';
import { moduleA } from 'ts-issue-module-a';

export const moduleB = (age: number): SomeInterface => {
  const data = moduleA(age.toString())
  const ageString = data.age;

  const value: SomeInterface = {
    age: parseInt(ageString, 10)
  }
  
  return value;
}

ts-module-a (module-b dependency)

import { SomeInterface } from 'ts-typelib-example';

export const moduleA = (age: string): SomeInterface => {
  const value: SomeInterface = {
    age
  };

  return value;
}

For SomeInterface it exists in 2 versions: (1.0.0) where age is a string and (2.0.0) where age is a number. (breaking change version.

Expected behavior:

The expected behaviour is that the returned interface by moduleB should be the 2.0.0 version interface (as expected from node_modules resolution first level). Instead, VSCode displays an error telling to import SomeInterface to resolve the conflict.

Actual behavior:

TypeScript cannot resolve the type returned by the moduleB function creating undesirable errors in dependencies. (This error could exist in thousands of dependencies due to developers cant update 2nd level dependencies from third party modules).

Playground Link:

https://github.com/imt-jaime/ts-monorepo-issue-example

Related Issues:

#29221

** Repository Structure **

  • node_modules
    • module-b (linked)
  • src
    • index.js
    • packages
      • module-b (linked globally)
        • node_modules
          • ts-typelib-example (v2.0.0)
          • module-a
            • node_modules
              • ts-typelib-example (v1.0.0)
            • src
            • package.json
        • src
        • package.json
      • ts-typelib-example
        • node_modules
        • src
        • package.json
  • package.json

More information can be found in the repository (README.md)

@sandersn sandersn added Bug A bug in TypeScript Needs Investigation This issue needs a team member to investigate its status. labels Aug 29, 2019
@RyanCavanaugh RyanCavanaugh removed the Bug A bug in TypeScript label Sep 25, 2019
@RyanCavanaugh RyanCavanaugh added this to the TypeScript 3.8.0 milestone Sep 25, 2019
@imt-jaime
Copy link
Author

I've still having problems with TypeScript and types resolution, not only with monorepositories: As i said, npm allows to install more than one breaking change version installed (usually the older one is installed in specific modules and newer in node_modules root) and TypeScript stills having problems with modified types and interfaces.

This problem could be extended to all the community in the future due to not all developers have the most recent version of all modules. As more typescript modules you have installed the risk is increased due to more version modules exists in your node modules. The issue seems to be also related to this commit #33567.

While using "traceResolution" option in compiler options, node resolution behavior seems to be right, it goes from the file to the project root looking for on each iteration "./node_modules/module" but, somehow types are like "stored" in a paths cache which confuses module folders. I've seen sometimes VSCode telling that there are multiple matches with a module absolute import path (Maybe should select the closest one).

@sheetalkamat
Copy link
Member

@imt-jaime Can you please update your repro and see if it still repros.. I followed exact steps in your repro and I get completely different error:

Here are the steps I followed:

  • Clone the repo
  • cd src\packages\ts-issue-module-b
  • npm link
  • cd cd ......\
  • npm link ts-issue-module-b
  • tsc
src/index.ts:4:7 - error TS2742: The inferred type of 'valueB' cannot be named without a reference to 'ts-issue-module-b/node_modules/ts-typelib-example'. This is likely not portable. A type annotation is necessary.

4 const valueB = moduleB(3);
        ~~~~~~

src/packages/ts-issue-module-a/src/index.ts:1:31 - error TS2307: Cannot find module 'ts-typelib-example'.

1 import { SomeInterface } from 'ts-typelib-example';
                                ~~~~~~~~~~~~~~~~~~~~


Found 2 errors.

@sheetalkamat sheetalkamat added Needs More Info The issue still hasn't been fully clarified and removed Needs Investigation This issue needs a team member to investigate its status. labels Jan 30, 2020
@imt-jaime
Copy link
Author

imt-jaime commented Jan 31, 2020

Hello @sheetalkamat , i've updated the repository to version 3.7.5 (current) and it stills happening.

The steps to reproduce the issue were the same except for the last one (npm run typescript which is tsc command). However the error ive found is different from yours, it seems link didn't installed module-b dependencies. Maybe you missed to install project dependencies? (npm install at root)

Correction:
(confirmed, i've got your error when base project has no installed dependencies) I've updated repository instructions. However this error is also unexplained due to 'ts-typelib-example' is also installed in 'ts-issue-module-b' .
Doesn't compiler looks inside the closest node_modules when "moduleResolution": "node" is specified?.

Thats the error I get by running typescript:

src/packages/ts-issue-module-a/src/index.ts:5:5 - error TS2322: Type 'string' is not assignable to type 'number'.

5     age
      ~~~

  node_modules/ts-issue-module-b/node_modules/ts-typelib-example/src/index.ts:2:3
    2   age: number;
        ~~~
    The expected type comes from property 'age' which is declared here on type 'SomeInterface'


Found 1 error.

Additional Information:

Working in another projects stills the same error, I think typescript creates a libraries cache like and selects randomly what library to check avoiding node_resolution without taking care of versions or node_modules structure.

@imt-jaime
Copy link
Author

The error displayed by VSCode:
typescript-error

@sheetalkamat
Copy link
Member

@imt-jaime thank you for correcting the repro.. I will investigate this..

@sheetalkamat sheetalkamat added Needs Investigation This issue needs a team member to investigate its status. and removed Needs More Info The issue still hasn't been fully clarified labels Jan 31, 2020
@sheetalkamat
Copy link
Member

Ok this was so confusing repro with so many copies of packages and each one with a long name.. But I have diagnosed this and it seems the error reported is correct...

Here is the structure after following your instructions::
image

From the structure the module ts-typelib-example from src/packages/ts-issue-module-a/src/index.ts is resolved to node_modules/ts-typelib-example/index.ts which exports things from node_modules/ts-typelib-example/src/index.ts which contains the definition of SomeInterface with age as number..

When I look into package json at the src/packages/ts-issue-module-a does say dependency is on ts-typelib-example@1.0.0 but the package.json at the root folder contains its version 2.0.0.0 as shown below.. Note that module resolution does not look at package.json for file its resolving module from but just traverses it to find node_modules folder in ancestor directories. So this behavior seems correct and instead you have incorrect setup..

image

@sheetalkamat sheetalkamat added Working as Intended The behavior described is the intended behavior; this is not a bug and removed Needs Investigation This issue needs a team member to investigate its status. labels Feb 3, 2020
@sheetalkamat sheetalkamat removed their assignment Feb 3, 2020
@imt-jaime
Copy link
Author

Error is exactly what you said. TypeScript can confuse modules from ancestors or even modules in another branches. I am sorry about the complexity of the repository. It is a complex error but i think it is the minimal reproduction of the error.

@sheetalkamat
Copy link
Member

Well from typescript perspective that is intended behavior though.. The error looks correct based on how the resolution works with the folder structure present in the repro scenario..

@typescript-bot
Copy link
Collaborator

This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

@tpluscode
Copy link

If anyone find this issue, it seems fixed on the next package today (March 23rd) :)

@dingfanATyykj
Copy link

Fixed by yarn cache clean , remove node_modules and install again.

@cprcrack
Copy link

I had this issue because one of my dependencies (A) had a peerDependency listed as B@0.1.8 and I had to use B@0.2.0 in my root package.

I first tried using selective version resolutions to force A into using B@0.2.0, but that didn't work (it could work for you if you use semver compatible versions).

What I ended up doing is installing B@0.2.0 in my root package as an alias, so that there is no conflict on types because it will be treated as a different package in a different namespace. Then you just need to be careful not to mix B@0.1.8 and B@0.2.0 types in your code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

8 participants