yarn icon indicating copy to clipboard operation
yarn copied to clipboard

@types packages are not installed as expected

Open fazouane-marouane opened this issue 6 years ago • 23 comments

Do you want to request a feature or report a bug?

Bug

What is the current behavior? I have some projects in typescript and when I install type dependencies (@types packages) I get weird errors. Those errors mean that there are at least two conflicting versions of those type definitions that I installed. I don't get those errors when I use npm.

If the current behavior is a bug, please provide the steps to reproduce.

When you have the following package.json

{
  "name": "yarn-types-bug",
  "version": "1.0.0",
  "description": "",
  "dependencies": {
    "@types/react": "^15.6.2",
    "@types/react-dom": "^15.5.4"
  }
}

yarn install gives the following node_modules

├─ @types/[email protected]
│  ├─ @types/react@*
│  └─ @types/[email protected]
└─ @types/[email protected]

What is the expected behavior? npm install gives:

├── @types/[email protected]
└─┬ @types/[email protected]
  └── @types/[email protected] deduped

Please mention your node.js, yarn and operating system version.

  • OS macOS Sierra 10.12.6
  • node 8.5.0
  • npm 5.3.0
  • yarn 1.0.2

fazouane-marouane avatar Sep 17 '17 10:09 fazouane-marouane

Hello,

Sorry if this will seem like a rant, but this is a serious issue for all Typescript users. Yarn as of today does not work at all with typescript @types packages. It used to, it doesn't now. It's been a week that I'm using npm for my projects (mostly typescript projects). It's been more than a year that I use yarn for various projects I enjoy all the features that it provides but now I'm being forced to use npm just to get basic package installation working.

I would be very grateful if someone from the core team acknowledged reading this issue. Thanks

fazouane-marouane avatar Sep 25 '17 21:09 fazouane-marouane

I also get outdated @types packages since their versioning are minor bumps most of the time, but significant changes since they are types. They only thing that fixed this was nuking node_modules, yarn cache clean, remove yarn lock - every time i need to bump @types.

beckend avatar Oct 03 '17 12:10 beckend

Can we establish whose problem this is at least?

The problem as far as I can see is that the latest @types/react is versioned '16.x' and the latest @types/react-dom has a dependency of '@types/react': '15^'. As such, yarn seems to be installing the latest version of @types/react and @types/react-dom, but because the dependency of the later is '15^', it installs the older types/react in its node_modules.

Typescript then has a sulk because there are two @types/react present.

So is it a case that:

  • Yarn shouldn't be installing two versions of the same package (or should be making an exception for @types/*)
  • TypeScript should be able to handle multiple versions of the same typings file better
  • The typings file authors should update their dependency of react-dom to be 16^ ?

... or maybe something else?

jamiewinder avatar Oct 18 '17 08:10 jamiewinder

@jamiewinder as explained in the issue description, that’s mainly a yarn related issue. As far as I’m concerned, if npm can install @types packages without hassle I assume yarn should do the same. It’s not a react types related either, since the issue can be reproduced with other @types packages. So my guess is that yarn should better handle type packages by installing them in a flattened mode and discard inner type dependencies in favor of types requested in the project’s package.json.

fazouane-marouane avatar Oct 20 '17 21:10 fazouane-marouane

My observation is that cause of this issue is yarn considers * as newest version and @types packages have often dependencies versioned as *. According to npm semver docs * should be any version (Any version satisfies).

If project.json has explicit dependencies for eg @types/react and @types/react-dom where react is not the newest it would install @types/react twice (package.json version and the newest one for @react-dom). npm does it correctly and if package.json has explicit dependecies it only installs this version even if inner dependencies has *.

I am experiencing this issue also with yarn versions 0.21.3 and 1.3.2...

ahz avatar Nov 07 '17 16:11 ahz

Yarn as of today does not work at all with typescript @types packages. It used to, it doesn't now. It's been a week that I'm using npm for my projects (mostly typescript projects).

So it sounds like this regressed recently? If you can isolate a working version, that could help to isolate the change that created the bug.

On the other hand, @ahz is seeing this all the way back in 0.21.3...

jcrben avatar Nov 25 '17 20:11 jcrben

Noticed this today as well. The following package.json:

{
  "name": "test",
  "version": "1.0.0",
  "private": true,
  "dependencies": {
    "@types/create-react-class": "^15.6.0",
    "@types/react": "15",
    "@types/react-dom": "15"
  }
}

Is resolved to the following yarn.lock:

# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


"@types/create-react-class@^15.6.0":
  version "15.6.0"
  resolved "https://registry.yarnpkg.com/@types/create-react-class/-/create-react-class-15.6.0.tgz#e711fc562e4fa1fc93710b6b202871d35981a5d0"
  dependencies:
    "@types/react" "*"

"@types/react-dom@15":
  version "15.5.6"
  resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-15.5.6.tgz#7794ff7822882b59b899c30294e1b1e62e97757e"
  dependencies:
    "@types/react" "^15"

"@types/react@*":
  version "16.0.25"
  resolved "https://registry.yarnpkg.com/@types/react/-/react-16.0.25.tgz#bf696b83fe480c5e0eff4335ee39ebc95884a1ed"

"@types/react@15", "@types/react@^15":
  version "15.6.7"
  resolved "https://registry.yarnpkg.com/@types/react/-/react-15.6.7.tgz#e910b6aace59d8d0b48dd679c2c03cffedafeec6"

The @types/react@* was resolved to a separate v16, instead of being deduped into:

"@types/react@15", "@types/react@^15", "@types/react@*":
  version "15.6.7"
  resolved "https://registry.yarnpkg.com/@types/react/-/react-15.6.7.tgz#e910b6aace59d8d0b48dd679c2c03cffedafeec6"

AviVahl avatar Nov 27 '17 14:11 AviVahl

https://github.com/DefinitelyTyped/DefinitelyTyped/issues/20350 this one sounds strongly related.

AllainPL avatar Dec 18 '17 10:12 AllainPL

Sad! Feel to give up the use of yarn, the yarn is not suitable for typescript developers.

XYUU avatar Jan 24 '18 10:01 XYUU

Yarn team, this is a pretty major issue. It essentially means that if you use typescript with yarn, you must use the latest versions of the @types packages. If not, typescript type validation usually breaks (due to incompatibilities of two versions of the same @types package).

I am forced to use npm in one of my newest projects due to this issue.

EDIT: and I now found the entire discussion at https://github.com/yarnpkg/yarn/issues/3951

AviVahl avatar Jan 25 '18 20:01 AviVahl

Have you tried to use the resolutions node in the package.json?

For me the TypeScript definition issues with react are solved by the following settings in package.json:

    "resolutions": {
        "**/@types/react": "15.6.0"
    }

Read more about it here.

jkanczler avatar Jan 26 '18 15:01 jkanczler

Is it ok and documented behavior for Yarn to add nested node_modules folder with second version of dependency? My fix for latest @types/react:

"resolutions": {
    "@types/react": "*"
}

fhucko avatar Mar 12 '18 13:03 fhucko

I found a workaround, by using types-installer, which does work with yarn.

cLupus avatar Apr 09 '18 11:04 cLupus

Is this going to be addressed?

srolel avatar Jul 05 '18 06:07 srolel

Just stumbled upon this issue. The lead problem is in @types/react-dom. Short answer is that by defining @types/react as a dependency (rather than a peerDependency), @types/react-dom is exposing itself to hoisting issue (hoisting is not a guarantee! we only guarantee that each package will get the dependencies it requests).

Long answer is detailed in the following article: Dependencies done right.

(As a side note, there's also another issue in Yarn which should do a better job at hoisting those dependencies, but that's unrelated: @types/react-dom should be able to work without this)

arcanis avatar Jul 31 '18 08:07 arcanis

@arcanis thanks for clarifying. so unless developers use the peer dependency field correctly we keep having this issue and the only workaround is by using

"resolutions": {
    "@types/react": "*"
}

Is this right? Besides, I think this is a serious issue for quite a few people (apart from react + typescript) and it would be nice if there was an option in yarn to either disable the hoisting or at least behave similarily to NPM in this regard, at least up to the point where the peerDependencies are done right;)

nachtfisch avatar Aug 15 '18 10:08 nachtfisch

so unless developers use the peer dependency field correctly we keep having this issue and the only workaround is by using

That unfortunately won't solve the issue (at least not in theory - maybe it does in practice, I haven't checked). The resolutions field doesn't remove the dependency from @types/react, it just changes the allowed range. The package manager is still allowed to duplicate react. The only way to solve this for good is by opening a PR in @types/react to ask them to use a peer dependency.

it would be nice if there was an option in yarn to either disable the hoisting or at least behave similarily to NPM in this regard, at least up to the point where the peerDependencies are done right;)

In fact we're going the opposite direction, and have various plans to enforce correctness more and more. Fix the affected packages now! 🙂

arcanis avatar Aug 15 '18 11:08 arcanis

Have you tried to use the resolutions node in the package.json?

For me the TypeScript definition issues with react are solved by the following settings in package.json:

    "resolutions": {
        "**/@types/react": "15.6.0"
    }

Read more about it here.

@jkanczler unfortunately this does not work with yarn workspaces :(

gitowiec avatar Feb 27 '19 12:02 gitowiec

Where does this stand currently? As far as I understand this apparently incorrect interpretation of what version * means is causing some breakage from time to time and had me manually editing the lockfile in some cases. From yarn's perspective it seems like the @types/packages should just use peerDependencies.

However from the TypeScript side it seems like the dependencies are somehow automatically generated, based on this PR https://github.com/microsoft/types-publisher/pull/371 And they don't want to make the dep a peerDependency because tools like VSCode are running eg npm install @types/leftpad and would expect that to install leftpad as well. But it sounds like npm doesn't install peerDependencies automatically.

sam-gronblom-rj avatar Sep 06 '19 01:09 sam-gronblom-rj

Have you tried to use the resolutions node in the package.json? For me the TypeScript definition issues with react are solved by the following settings in package.json:

    "resolutions": {
        "**/@types/react": "15.6.0"
    }

Read more about it here.

@jkanczler unfortunately this does not work with yarn workspaces :(

it worked for me by removing yarn.lock and having the resolutions block in the root package.json (I even included it in the workspace package.json, I am bored)

abumalick avatar Jun 07 '20 14:06 abumalick

Now, in 2022, I am using yarn 3.2.1 and React 17. I still had to add the following block to the root package.json to work around this bug:

  "resolutions": {
    "@types/react": "17.0.38"
  }

mattes3 avatar Jun 05 '22 07:06 mattes3

Still weird that after a long time yarn doesn't hoist * versioning correctly

ilijaNL avatar Aug 26 '22 06:08 ilijaNL

+1

demoh2019 avatar Sep 06 '22 10:09 demoh2019

Now, in 2022, I am using yarn 3.2.1 and React 17. I still had to add the following block to the root package.json to work around this bug:

  "resolutions": {
    "@types/react": "17.0.38"
  }

Thank you very much, I used this and it worked with yarn workspaces, but does it mean that yarn is supporting the "resolutions" field in package.json ? Is this documented somewhere ?

slevy85 avatar Nov 09 '22 12:11 slevy85

Is this documented somewhere ?

https://classic.yarnpkg.com/lang/en/docs/selective-version-resolutions/ https://yarnpkg.com/cli/set/resolution

michaelfaith avatar Nov 09 '22 12:11 michaelfaith

does it mean that yarn is supporting the "resolutions" field in package.json ? Is this documented somewhere ?

Well yes, we kinda invented it 😄

Regarding the initial issue which I only see now (we don't really look at this repository, development for modern releases of Yarn is on yarnpkg/berry), @types/react-dom should define @types/react as a peer dependency, not a regular one.

  • Dependencies listed in the dependencies field may be deduped, but if and how is entirely left to the package managers' heuristics. Not doing any hoisting would even be a perfectly valid behaviour.

  • Peer dependencies, on the other hand, guarantee that when the dependency will be accessed it'll be the exact same instance as the one provided by the direct ancestor. You can see it as a kind of dependency injection: you tell @types/react-dom what's the react version it must work with. This is what we want, for types.

It may look a purely theoretical issue, but keep in mind:

  • I mentioned the "package managers' heuristics". Heuristics, by definition, are a set of tradeoffs. What the hoisting result looks like will depend on what versions are in the tree, how many packages depend on them, how deep they are, ... all in all, hoisting is very unpredictable.

  • The peer dependency contract is very important in terms of hoisting as well. Without it, Yarn may generate a hoisting in such a way that @types/react-dom would access a different version of react than the one you provide (without entering into the details, peer dependencies instruct Yarn that packages with this name cannot be hoisted past the peer dependency position in the tree - they have a very important role).

In any case, I'm going to lock this thread as this isn't a Yarn issue. Modern versions of Yarn let you bypass this third-party issue by either:

  • Using the resolutions field (as suggested before)
  • Using the packageExtensions setting to add the missing peer dependency to @types/react-dom (hopefully until it gets fixed upstream; although I'm afraid not using peerDependencies is an intentional - and broken - choice from the DefinitelyTyped team).

arcanis avatar Nov 09 '22 12:11 arcanis