Closed mistic closed 7 months ago
Hm, it's a bit awkward in your case, since we technically never directly discover that react-router
is directly visible from your project folder (our symlink discovery is a bit heuristic based, so we only find them in paths we had to resolve a symlink across to access). If you had a react-router
import somewhere in the file already, we'd know we have a lookup available... Hm. @RyanCavanaugh today we don't use a package.json
for anything within a TS project, however with the recent changes to node resolution, we really should start considering it (so we can resolve package self names and "imports"
maps) - as part of that, we could maybe consider using the dependencies
manifest as a list of safe-to-access modules, like how we already use it for autoimports in the language server.
@weswigham Thanks for looking into the issue. What you wrote makes sense in my head as an explanation about why it is this bug happening. Let me know if I can be useful in any other way to move forward with this one as I really hope we can fix it!
I've got a repro which may help with the fix available here: paynecodes/ts-repro-type-annotation-require-symlinks. I don't want to hijack this issue if it's the wrong place, so let me know if a new issue is desirable.
The README lists references to similar issues I was able to dig up.
I have a set of npm packages where "types" points to a .ts (not a .d.ts) file. Reason being I can directly jump to the implementation with the IDE. The issue I'm running into is the following:
An npm package B
that depends on another npm package A
. A factory function obj_
that returns a value with a custom type defined or referenced by pkg A
. pkg B
has export const obj = obj_()
. Typescript compilation is successful. When another package C
imports the obj
from pkg B
, The inferred type of "obj" cannot be named without a reference to "path/to/pkg/A". This is likely not portable. A type annotation is necessary.
This cannot happen. At the very least, it would be useful to have a setting in tsconfig.json
for the TS compiler to make pkg B
fail compilation unless const obj = obj_()
has a type annotation. Otherwise, the pkg B
has to be fully built & installed by another pkg C
as an npm package to test. Inferring the type across packages (not in rootDir
) would be the more ergonomic solution, as long as performance does not suffer.
Ā At the very least, it would be useful to have a setting inĀ tsconfig.jsonĀ for the TS compiler to make pkgĀ BĀ fail compilation unlessĀ const obj = obj_()Ā has a type annotation.Ā
There is one. declaration: true
.
My understanding of declaration: true
is that a *.d.ts
file is created. It would be great to navigate directly to the *.ts
source.
To support both .ts & .d.ts files in an npm package, something like "declarationDir": "dist"
is necessary, otherwise, *.ts*
files will be imported due to import precedence.
Another minor issue that I have to account for is with single file components which are compiled separate from Typescript. For example a svelte or vue component. These components will need to be copied over to the dist
directory during npm run build
, since npm does not support links within packages.
These are both minor but annoying issues. Particularly annoying when working with monorepos/multirepos with many packages. It's rare & tooling can fix the build issues. It seems like *.d.ts is useful in having a standard to ensure that type inference works in all cases, but it unfortunately breaks navigation. Of course the tools (VSCode, Jetbrains) would need to address the navigation problem as it stands.
Would it make sense to annotate the path to the source of the .d.ts file in a comment, like a .map file?
My understanding ofĀ declaration: trueĀ is that aĀ .d.tsĀ file is created. It would be great to navigate directly to theĀ .tsĀ source.
Also set declarationMap: true
.
Check if this works for you: https://github.com/microsoft/TypeScript/issues/29808#issuecomment-540292885
@weswigham @btakita not related with that initial issue but with your last discussion: declarationMap
has also a buggy behaviour when used along sourceRoot (which is vital in some cases) https://github.com/microsoft/TypeScript/issues/31873 we are still waiting for a solution on that other issue.
Check if this works for you: #29808 (comment)
doesn't help in my case. yarn workspaces monorepo setup with monorepo/pkg1 depending on monorepo/pkg2 & node_modules/pkg1 monorepo/pkg2 depending on node_modules/pkg1 Using same version of external/pkg1
I get this issue in a Rush monorepo where a project depends on cmd-ts
. Strangely, it only affects VSCode. I have to do the path alias trick, restart TS, but then it works. An I can remove the path alias. Very strange.
I get this issue throughout many scenarios when using a Rush monorepo. Rush, by default, uses pnpm (pnpm workspaces is recommended). I haven't been able to track down the root cause, but I have scoured this issue tracker and subscribed to many topics hoping someone squashes this.
Im using a pnpm
monorepo and had a similiar problem which I could resolve by setting
baseUrl: "."
inside the package tsconfig.json
In my case:
When I use declaration: true
and yarn
as package manager -> got same error cannot be named without a reference to 'styled-components/node_modules/@types/react
After researching I found mismatch versions of @types/react
for my repo and dependency styled-components/node_modules/@types/react
If run yarn install --flat
, manually fill subpackage resolutions and run yarn build
- problem is disappear
@InsOpDe pnpm
also installs flat dependencies for monorepo with resolutions and you avoided my problem :)
In my case, add preserveSymlinks
for resolve it
{
"compilerOptions": {
"preserveSymlinks": true
}
}
@mistic try this: add below code into this file: https://github.com/mistic/reproduce-typescript-problem-when-symlinking-node_modules/blob/main/project/tsconfig.json
{
"paths": {
"@types/react-router": ["../../deps/node_modules"]
},
}
it works!
In my case, add
preserveSymlinks
for resolve it{ "compilerOptions": { "preserveSymlinks": true } }
This solved it for me too, but why ? :thinking:
Is there any way to designate parts of your code where this error is ignored? I'm getting this error, but in a part of my code that will never be exported for an end user (in private code, I mean).
FWIW, I'm getting this when compiling https://github.com/facebook/flipper on Windows, where I have my code on drive ("I:") that is actually just symlinked (or whatever that is on Windows) to a directory on the "C:" drive.
Running the compile from the actual "C:" location makes this error go away. Strange.
Using preserveSymlinks
didn't make any difference for me.
For my case, I've found the following:
It only occurs when "declaration": true
(no idea why however)
You can work around it by either:
paths:{}
in compilerOptions
node_modules
folder of the symlink'd location (not practical but it does fix the problem)I removed "declaration": true
, "preserveSymlinks": true"
and restart ts server
I'm using pnpm and I made sure that I only had one version of react-query
(in my case) across the entire codebase and it started working, restarted TS server, and added declarationMap: true
. So one of these fixed it...
I use pnpm.overrides remove the duplicate dependencies and resolved this problem.
"preserveSymlinks": true
doesn't resolve all errors that I have. I also use pnpm
and typescript
together. Previously I used yarn and typescript and everything was fine.
Now, I have The inferred type of 'someVar' cannot be named without a reference to '@pnpm-test/core-config/node_modules/yup/lib/string'.
This is likely not portable. A type annotation is necessary. and have no idea how to resolve that.
This appears if I set
"baseUrl": "./",
"paths": {
"*": [
"node_modules/*/"
]
}
If I remove that, I also have the same issue but in other places.
The way to fix this exact problem described above was setting path to exact module (yup
in my case), but then I still get other similar errors. That's super frustrating.
I also set declaration: false
for testing purposes but had no luck having it working.
I was able to setup my repository so that it works with PNPM and NPM for installation in a monorepo workspace. I've found that this bug happens with PNPM but goes away with NPM
root
Appears to be a bug in dependency resolution. Appears to be related to how PNPM does symbolic folder links. This specifically happens when I expose a type from a child dependency.
As long as all the types in the sub module are internal to that module it works fine. But if I reference a type from a sub/sub module and then build it will fail
For science I've also tried pnpm i --shamefully-hoist
and it fails the same.
None of the band aides mentioned above have seemed to resolve it for me using PNPM.
preserveSymlinks
to true or false as others have suggested.baseUrl: "."
tsconfig.json
Obviously disable declaration
resolves the build. But the whole point is to create the index.d.ts
declaration file that is blowing up
It fails consistently in all forms:
tsc index.ts --declaration --emitDeclarationOnly --allowSyntheticDefaultImports --outfile dist/index.d.ts
I managed to get this working. The steps would be to install all troublesome node_modules in the root package.json, then add this (in my case) to tsconfig.json at the root
"paths": {
"react": ["node_modules/@types/react"], // fair I am using this
"react-query": ["node_modules/react-query"], // fair I am using this
"csstype": ["node_modules/csstype"] // this is causing issues from within react using CSSProperties
}
And this makes sense due to the nature of pnpm, it installs the actual files into node_modules/.pnpm/<package>@<version>/node_modules
, then symlinks this into each workspace. You cannot guess this path, hence installing the packages into the root package.json will have them symlinked into the node_modules at the root, and you can reference them through paths
.
I am not sure if this is a typescript
issue or a pnpm
issue, but I do think having to go through those steps is sub-optimal š
@tbergquist-godaddy Not sure I understand. In my setup I'm referencing a package (A) within my mono repo into another package (B) in the same folder.
(A) References a third party dependency that is the one being referenced as an error in (B) when I import A and use it
In my case PNPM installs a symbolic link of (A) into (B) node_modules. (A) then contains a node_modules symbol link to the third party package
But as far as TSC should be concerned this is standard dependency hierarchy and it should be able to find all the typings.
Well, from the error I get The inferred type of 'useSaveLanguage' cannot be named without a reference to 'packages/whitelabel/node_modules/react-query/types
. And this error is coming from packages/language/...
. which gets its types from packages/language/node_modules/react-query/types
.
Both of these might be symlinked to the same type, but I take it that tsc doesn't follow symlinks and see the paths as different path and then types.
@tbergquist-godaddy Oh that's interesting that yours references the folder path fully. Mine references the module name then path
The inferred type of 'Ethereum' cannot be named without a reference to '@decentology/hyperverse-evm/node_modules/@rainbow-me/rainbowkit'. This is likely not portable. A type annotation is necessary.
It's frustrating that this problem goes away when I use npm install
beause while I don't get this error I have other issues that require that I use PNPM. So it leads me to believe that it's just a setting away in PNPM to resolve the error
Upon further trial and error. I can confirm that setting the path in tsconfig.json
does in fact work
However I'm not sure I understand why
Here is how I fixed it:
I created a .npmrc
in the package (B) that was having the problem and set. Which is nice because I can localize what needs hoisted per package: Reference: https://pnpm.io/npmrc#public-hoist-pattern
EDIT: I thought .npmrc in sub folder worked. Seems that may have been a fluke. Adding it to root .npmrc more reliable
public-hoist-pattern[]=*@rainbow-me*
public-hoist-pattern[]=*@ethersproject*
Which were the two projects that had errors with the The inteferred type....
I then ran pnpm i
to install the modules. This lifted thw two packages into the root mono repo node_modules folder
I then went back to package (B) and configured the tsconfig.json
as others have suggested to point to that path. Reference: https://www.typescriptlang.org/tsconfig#paths
"paths": {
"@rainbow-me/rainbowkit": ["../../node_modules/@rainbow-me/rainbowkit"],
"@ethersproject/providers": ["../../node_modules/@ethersproject/providers"],
}
No more error. Yay!
So it's worth noting that the symbolic link path originally would have been nested like
node_modules/@decentology/hyperverse-evm/node_modules/@rainbow-me/rainbowkit
But when setting that nested path in my trial and error in the tsconfig.compilerOptions.path it fails to resolve the typings. But hosting it to the top resolves the problem. I assume the nested path would be the default path it would be using :shrug:
Yeah, using public-hoist-pattern
will also work, since it essentially does the same as adding it to your package.json folder, it will symlink it to the root node_modules
of your workspace.
It might be the preferred approach since you don't have to stick dependencies you are not directly depending on in your package.json file.
I have this error with @trpc/server
in a monorepo, using yarn@3.2.1
.
I tried all the solutions in this issue and none worked. š
I've made an issue on trpc
repo with a repro : https://github.com/trpc/trpc/issues/1945
edit
It seems like I have to use a wildcard in the paths
and it solves the issue ā
{
"extends": "@acme/tsconfig/node",
"compilerOptions": {
"baseUrl": "src",
"outDir": "./dist",
"rootDir": "./src",
"paths": {
"@trpc/server/*": ["../../../node_modules/@trpc/server/*"]
}
},
"include": ["src/**/*.ts"]
}
Like @jsheely I don't understand why it works that way and if it's a typescript resolution issue or if it's a misuse of typescript at the library level.
In a Vue 3 app I commented out "composite": true
under compilerOptions
, because it sets declaration: true
In a Vue 3 app I commented out
"composite": true
undercompilerOptions
, because it setsdeclaration: true
this will break your composite build.
In a Vue 3 app I commented out
"composite": true
undercompilerOptions
, because it setsdeclaration: true
this will break your composite build.
Thank you for the notice. But what exactly is a composite build?
In a Vue 3 app I commented out
"composite": true
undercompilerOptions
, because it setsdeclaration: true
this will break your composite build.
Thank you for the notice. But what exactly is a composite build?
It allows you to skip the build process if your project has been already built.
The composite option enforces certain constraints which make it possible for build tools (including TypeScript itself, under --build mode) to quickly determine if a project has been built yet.
In a Vue 3 app I commented out
"composite": true
undercompilerOptions
, because it setsdeclaration: true
this will break your composite build.
Thank you for the notice. But what exactly is a composite build?
It allows you to skip the build process if your project has been already built.
The composite option enforces certain constraints which make it possible for build tools (including TypeScript itself, under --build mode) to quickly determine if a project has been built yet.
Thank you. It seems the option "composite": true
is only present in the generated Vue 3 app boilerplate if vitest
is used.
See: https://github.com/vuejs/create-vue-templates
It isn't included in the tsconfig.json
in a regular typescript setup. I don't think it will cause problems as it seems to be only recommended with vitest.
Reading this long thread, I understand the root cause is somehow related to symbolic links.
I just don't get why TS compiler should care. Isn't it simply of operating system behavior ? Shouldn't TS compiler just "blindly" read the file, whether it's linked or not ?
The inferred type of 'authSlice' cannot be named without a reference to '.pnpm/immer@9.0.14/node_modules/immer/dist/internal'. This is likely not portable. A type annotation is necessary.
This is what I get. I'm using pnpm, t ypescript and monorepo. To be precise, I'm using this: https://github.com/NiGhTTraX/ts-monorepo
authSlice
is actually createSlice
, and createSlice
is imported from @reduxjs/toolkit
. I have read the entire thread and setting the baseUrl = "."
didnt work.
EDIT: I also added
"paths": {
".pnpm/immer@9.0.14/*": ["node_modules/.pnpm/immer@9.0.14/*"]
},
but that also didn't work.
EDIT 2: I managed to fix the error by deleting
"declaration": true,
"declarationMap": true,
from root tsconfig.build.json
I made another small repo, based on rush and pnpm. It consists of two packages, and declarations are generated for both with rush build:dts
, similar to what I have in a bigger project.
https://github.com/atsikov/ts-not-portable-error
Running the command throws an error for the second package
src/index.ts(3,14): error TS2742: The inferred type of 'useRunMutation' cannot be named without a reference to '../../common/node_modules/react-query/types'. This is likely not portable. A type annotation is necessary.
Both packages use react-query
as a dependency, however for the common
it is a peer (added to dev as well), as this package is not supposed to be used on its own. Generated declarations for common
contain import('react-query').{SomeType}
and it is the reason for "cannot be named" error.
I would expect TS to try to resolve react-query
relatively to both definitions package (where the dependency is not installed because of being a peer) and to the hosting package (where the dependency exists). It looks like TS only tries to perform a former resolution and fails to do so.
This was probably already mentioned somewhere, but I didn't find a clear explanation. It is some design limitation, or was it done on purpose, or just something that was not considered?
This related issue #37960 proposes a new option in tsconfig to bypass this compile time check. This new options would be useful for incremental builds, where the declaration files are not shipped as artifacts (e.g. monorepo, workspaces, etc...).
That issue includes a patch that could be applied to "typescript". I'd be interested if it fixes the issues described here.
That issue includes a patch that could be applied to "typescript". I'd be interested if it fixes the issues described here.
Didn't work for me š
any body has a solution?
human err
Since this has to do with hoisting, switching the function declarations from const
to function
resolved this for me. I encountered this when exporting the configurations for my redux store
Before:
The inferred type of 'setupStore' cannot be named without a reference to 'XXX'. This is likely not portable. A type annotation is necessary.
export const setupStore = (preloadedState?: PreloadedState<RootState>) => { return configureStore({...}); }
After: (no errors)
export function setupStore (preloadedState?: PreloadedState<RootState>) {
return configureStore({...});
}
I managed to fix this by adding "declaration": false
to compilerOptions
in tsconfig.json
for my package, adding it here in case it helps someone else.
There is a related issue (#29808) as implicitly pointed out by @nwaughachukwuma in his comment. I solved it after following @akash-rajput\'s answer within the same thread.
To quote:
Happens when we have conflicting versions of a package installed. A temporary solution would be to remove the package mentioned from peer dependencies of the plugin giving the error.
Or install the exact version of common dependency
In my case, I had linked a local NPM package with peer dependency \@nestjs/common\@^9.0.7 to a monorepo that had \@nestjs/common\@^8.0.0 installed.
I'm using typescript@4.7.2
.
In my case, add
preserveSymlinks
for resolve it{ "compilerOptions": { "preserveSymlinks": true } }
This worked for me.
Note: I had to restart my TypeScript Server for this to have an effect on my IDE
thanks @PabloRosales, that worked for me š Just one question, do you know what side effects we can have in the typecheck if we enable that? š¤ is it safe?
Bug Report
š Search Terms
inferred type cannot be named, symlink node_modules
š Version & Regression Information
I'm verifying the problem on the
typescript@4.1.3
. I've not tried older versions but at least is also reproducible on the@next
version as of today.It is probably a regression or a corner case related with other issues opened and already closed like:
āÆ Playground Link
Link for a repo where the problem is being reproduced
š» Code
All the relevant code can be found at https://github.com/mistic/reproduce-typescript-problem-when-symlinking-node_modules
It is just reproducing a similar setup that I had on other project that was generating the problem:
withRouter
withinreact-router-dom
that is just a plain export from the same type onreact-router
.š Actual behavior
I got the following error:
š Expected behavior
I was expecting no error at all and that the typescript compiler was just able to find all the respective modules. I've tried everything that I thought was related like enabled the
preserveSymlinks
. The only thing that stops the error is importing thewithRouter
type directly fromreact-router
and not fromreact-router-dom
but that doesn't make very sense because I actually want to use thereact-router-dom
on a couple of places.\cc @weswigham @sheetalkamat @andrewbranch because I saw you previously worked to try to solve similar issues.