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

"The inferred type of X cannot be named without a reference to Y" (TS2742) occurs when multiple modules with the same package ID are resolved #47663

Closed
renke opened this issue Jan 30, 2022 · 101 comments
Assignees
Labels
Needs Investigation This issue needs a team member to investigate its status.

Comments

@renke
Copy link

renke commented Jan 30, 2022

Bug Report

🔎 Search Terms

  • TS2742
  • cannot be named without a reference

🕗 Version & Regression Information

Problems occurs with 4.5.x and 4.6.x and most likely earlier versions (I've tried a few other versions). It stills occurs on 4.7.0-dev.20220321.

⏯ Playground Link

I've created minimal repository that shows the problem: https://github.com/renke/typescript-package-id-merge-repro

The problem occurs when using pnpm (due to the modules layout it uses). No problems occur when using npm/yarn.

To reproduce the problem run pnpm install and then pnpm check pnpx tsc -b.

💻 Code

I don't think the code itself matters to much except from the fact that it in fact does not have explicit type annotations (which is kind of the idea when using zod and by extension @renke/vommer).

import { vod } from "@renke/vommer";
import { z } from "zod";

export const UserId = vod("UserId", z.string());

export type UserId = z.infer<typeof UserId>;

export const Email = vod("Email", z.string().min(0));

export type Email = z.infer<typeof Email>;

export const User = vod(
  "User",
  z.object({
    id: UserId,
    email: Email,
  })
);

export type User = z.infer<typeof User>;

🙁 Actual behavior

The following error occurs when trying to build a composite TypeScript project (same happens when just using declaration: true).

The inferred type of 'User' cannot be named without a reference to '.pnpm/@[email protected]/node_modules/@renke/vo'. This is likely not portable. A type annotation is necessary.

The dependency tree of @renke/vommer

@renke/vommer 0.2.0
├── @renke/vo 0.2.0
└─┬ @renke/vod 0.2.0
  └── @renke/vo 0.2.0

Looking at the resolution trace TypeScript tries to resolve @renke/vo two times the first time from @renke/vommer and the second time from @renke/vod. Both end up having the package ID @renke/vo/dist/[email protected].

Using "preserveSymlinks": true doesn't solve the problem in so far that the error disappears but the type is inferred as any, because the dependencies of @renke/vommer are not found. Also I don't actually want to use it.

🙂 Expected behavior

The error should not occur when there are two (or more) modules that have the same resolved package ID. It would make sense for the error to occur when they have different versions.

@zengguirong
Copy link

same problem

@RyanCavanaugh RyanCavanaugh added the Needs Investigation This issue needs a team member to investigate its status. label Feb 10, 2022
@RyanCavanaugh RyanCavanaugh added this to the Backlog milestone Feb 10, 2022
@renke
Copy link
Author

renke commented Mar 16, 2022

So, aside from finding a solution to this problem, is my assumption correct that having multiple packages with typings that have the same version should not cause any problems?

I'd also appreciate any hints on where to look at the source code to solve this problem.

@dohooo
Copy link

dohooo commented Apr 24, 2022

same problem!

@quadristan
Copy link

@renke i have a repro where everything has the same version here : https://github.com/quadristan/ts-indirect-type-reference-bug

@agmitron
Copy link

same problem :( have you solved it?

@renke
Copy link
Author

renke commented Jul 15, 2022

I haven't solved it yet, but there is also a similar issue #48212 with a milestone of TypeScript 4.8.0. Let's hope it will be solved soon.

@StarHosea
Copy link

same problem

@kiastorm
Copy link

kiastorm commented Aug 24, 2022

I got this issue because the mentioned dependency had this code in its index.d.ts:

declare module 'react' {
  interface DOMAttributes<T> {
    css?: InterpolationWithTheme<any>
  }
}

and the file it was complaining in was using React.HTMLAttributes<HTMLElement> which references React.DOMAttributes. I worked around this issue by omitting the declared properties Omit<React.HTMLAttribute<HTMLElement>, "css">

@laurix-wizard
Copy link

Same problem :(

@vaibhavkumar-sf
Copy link

Same Problem for me too :(

@ivanbanov
Copy link

is there any expected timeline for a fix for this problem?

@grmkris
Copy link

grmkris commented Sep 15, 2022

same here

@patroza
Copy link

patroza commented Sep 16, 2022

@RyanCavanaugh

@yingpengsha
Copy link

Same problem :(

@Evertt
Copy link

Evertt commented Sep 26, 2022

same here

1 similar comment
@xlboy
Copy link

xlboy commented Sep 28, 2022

same here

@shellscape
Copy link

What's worse is that neither // @ts-ignore nor // @ts-expect-error will allow us to ignore the incorrect error. This is a pretty gnarly bug.

@mrmeku
Copy link

mrmeku commented Oct 4, 2022

This bug occurs pretty readily when using pnpm since the node_modules directory layout is different under pnpm than npm/yarn. Any npm package whose types reference another npm package's type will generate the error

I've made a minimal reproduction here: https://github.com/mrmeku/portable_types_repro

@shellscape
Copy link

I've been deep-diving the issues related to this error and symlinks and pnpm specifically. Since 2019 it appears that this regression is reintroduced at least twice for each major version. That would suggest that tests are not sufficient for the case, nor to catch the regression.

@quadristan
Copy link

I have a repro + a workaround/solution here

https://github.com/quadristan/ts-indirect-type-reference-bug

tl-dr:

import type {} from "Y"; // or whatever Y really refers to

@i7eo
Copy link

i7eo commented Oct 16, 2022

I have a repro + a workaround/solution here

https://github.com/quadristan/ts-indirect-type-reference-bug

tl-dr:

import type {} from "Y"; // or whatever Y really refers to

Nice job! This is by far the best practice.👍

@RyanCavanaugh
Copy link
Member

I've been deep-diving the issues related to this error and symlinks and pnpm specifically. Since 2019 it appears that this regression is reintroduced at least twice for each major version. That would suggest that tests are not sufficient for the case, nor to catch the regression.

The reason you see a history of this "regressing" at each version is that pnpm patches TypeScript when you install it, so every time TS updates, there's a few days where it appears to not work because pnpm hasn't updated their patching code yet.

@RIP21
Copy link

RIP21 commented Oct 17, 2022

@RyanCavanaugh really? Do PNPM is patching TS in order for it to be compatible each and every time it installs it? That's a huge surprise for me really. Feels very unsustainable and kinda scary. Why is TSC itself is not compatible with PNPM? I hear about the first time in my life and never saw anything like that in the PNPM change log (not that I reading them (aside from major releases)) :)

@shellscape
Copy link

shellscape commented Oct 17, 2022

I've been deep-diving the issues related to this error and symlinks and pnpm specifically. Since 2019 it appears that this regression is reintroduced at least twice for each major version. That would suggest that tests are not sufficient for the case, nor to catch the regression.

The reason you see a history of this "regressing" at each version is that pnpm patches TypeScript when you install it, so every time TS updates, there's a few days where it appears to not work because pnpm hasn't updated their patching code yet.

could you point me at the code responsible for that? I'm a core contributor to PNPM and this is the first time I'm hearing of it. not to say that I disagree with you or that it isn't true, I'm just unaware of that.

@RyanCavanaugh
Copy link
Member

Sorry, you're right. I've misconfused this with yarn.

@Carnewal
Copy link

Carnewal commented Jan 30, 2024

I am having this issue as well, on v5.3.3.
...
This code alone generates 137 TS compiler errors, all in the format shown in the first screenshot. It's very unfortunate that this has been an ongoing issue for so long. It feels like I have hit a brick wall, as this one error essentially renders TS unusable. Every workaround that compiles involves stripping varying levels of contextual data from the type (such as explicitly setting the type of client to any), which undermines the entire point of using TypeScript in the first place.

@Threebow I spent some time trying to solve it for the redis package but wasn't succesful.
However, you can fix this by installing & using @redis/client (and other redis packages you rely on) directly instead of redis / node-redis.
Good luck!

@gabrielcosi
Copy link

Same problem when building a react library alongside styled-components with tsup

@lovrozagar
Copy link

Same problem here

@alvis
Copy link

alvis commented Feb 20, 2024

@ivancuric I could fix your issue with workaround #3 ("intermediary interface"), see https://github.com/pkerschbaum/repro-pnpm-types/commit/d3cd550990301959d058a3df65531c9a57d25146.

I forgot to mention one thing for workaround #3: it must be an interface, not a type. In the repo you provided, the broken code is:

// case #1, just reexport
export type RemoteObj = typeof exportedApi;

It stays broken when we do this:

// case #2, intersection type with empty object
export type RemoteObj = typeof exportedApi & {};

But it suddenly works when we do this:

// case #3, intersection type with interface
interface MyBlah {}
export type RemoteObj = typeof exportedApi & MyBlah;

That's of course very weird and suggests that there is a bug in TypeScript. I think in its inner workings, tsc "optimizes away" simple type aliases. Both case #1 and #2 can be simplified to just typeof exportedApi, which tsc tries to put into the types of the package imagecapture-main. But this leads - for valid reasons - to the This is likely not portable error. Case #3 seems to be not simple enough so tsc keeps the RemoteObj type around, solving the error.

Note that this is just my reasoning based on the observed behavior.

The fact that intersecting a type with an interface would make it suddenly works like a miracle indeed suggests something interesting. I'm not sure if @RyanCavanaugh @DanielRosenwasser has seen this hint, but if you haven't, please prioritize.

@Dorianslavov
Copy link

Dorianslavov commented Feb 23, 2024

I have managed to make the error go away by making a TypeScript Reference Type at the top of the file

In my case I was was importing useI18n function and spreading an object in it's parameter object like
useI18n({ ...someObj })

which caused this

The inferred type of useI18n cannot be named without a reference to .pnpm/@[email protected]/node_modules/@intlify/core-base . This is likely not portable. A type annotation is necessary.

✅ Fixed it by doing this

At the top of the file which used useI18n I've added the TS reference type like so

/// <reference types="@intlify/core-base" />

So to fix it, basically check the problematic package name ( in my case it was @intlify/core-base ) and add it as a TypeScript Reference Type like in the example above

@LOWE-7566
Copy link

use type casting it is always solved in that way

@matheo
Copy link

matheo commented Mar 31, 2024

import type {} from "Y";

This didn't work for my Nx monorepo with pnpm because in the workspace, peer dependencies were installed inside the library folder duplicating the package and causing the error. I opted to disable the peerdeps installation with:

.npmrc
auto-install-peers=false

and reviewed the peer dependencies warnings to confirm that they were installed, and added the ones missing: then I confirmed that everything ran as expected.

anyesu added a commit to anyesu/taro-demo that referenced this issue Apr 1, 2024
LiranCohen added a commit to TBD54566975/web5-js that referenced this issue May 2, 2024
* add reference types from dwn-sdk-js to avoid pnpm build error microsoft/TypeScript#47663

* add changesets

* add comment and link to PR explaining why the refence type is there
@pkerschbaum
Copy link

FYI there is some interesting discussion on this topic in microsoft/TypeScript#58176.

I find this idea for a solution by @eps1lon interesting (which is kind of bringing workaround #3.1 of my comment above into tsc itself):

Is there an option to enforce that whatever getMakeSubDep returns, is also exported from other_package? Then TypeScript could reference those exports instead. It should already do that today if you explicitly export the return type. But TypeScript favors import('sub_dep').Options over import('other_package').Options even if other_package explicitly exports Options.

@cumt-robin
Copy link

cumt-robin commented May 4, 2024 via email

@RyanCavanaugh
Copy link
Member

Closing per #42873 (comment)

@microsoft microsoft locked as resolved and limited conversation to collaborators May 6, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Needs Investigation This issue needs a team member to investigate its status.
Projects
None yet
Development

No branches or pull requests