Material UI styled component - "The inferred type of X cannot be named without a reference..."
Asked Answered
C

3

6

How is this TS issue resolved? My styled component is exported from a style.ts file and used inside the index.tsx file of my React component:

style.ts:

import { styled, Theme } from '@mui/material/styles';

type CardProps = {
    theme?: Theme;
    selected: boolean;
};

const Card = styled('div', {
    shouldForwardProp: (p) => !!p
})(({ theme, selected }: CardProps) => ({
    display: 'flex',
    flexDirection: 'column',
    padding: theme?.spacing(2),
    width: theme?.spacing(39.5),
    boxShadow: theme?.shadows[2],
    color: theme?.palette.grey[50],
    borderRadius: theme?.spacing(0.5),
    margin: `${theme?.spacing()} ${theme?.spacing(2)}`,
    ...(selected && {
        background: theme?.palette.grey[100],
        color: theme?.palette.getContrastText(theme?.palette.grey[100])
    }),
    ...(!selected && {
        cursor: 'pointer',
        border: `1px solid #DEE4EA`
    }),
    '&:hover': {
        ...(!selected && { color: theme?.palette.grey[100] })
    }
}));

export { Card }

index.tsx

import { Card } from './style';

const ExperimentCard = ({
    id,
    selected,
    handleSelectCard,
}: Props) => (
 <Card data-cy="experiment-card" id={id} selected={selected} onClick={() => handleSelectCard(id)}>
    ...
</Card>

TS issue:

Plugin typescript: @rollup/plugin-typescript TS2742: The inferred type of 'Card' cannot be named without a reference to '@mui/material/node_modules/@mui/system'. This is likely not portable. A type annotation is necessary.

One suggestion I have found, was adding the suggested reference into the tsconfig.json file like below, but with no luck.

"types": ["@mui/material/node_modules/@mui/system"],
Charmion answered 20/9, 2022 at 11:45 Comment(0)
L
5

I had this issue using mui styled with pnpm in a monorepo setting. After some digging it seems to be caused by typescript not playing well with nested transitive dependencies.

Here are some related issues on github where people discuss the root of the problem and pose some solutions:

Typescript Issue #36800

Typescript Issue #30858

I couldn't find a convenient solution that worked for pnpm, besides configuring nodelinker=hoisted, which defeats the purpose of using pnpm in the first place.

EDIT

It seems that installing @mui/system as a direct dependency worked, since @mui/system is now at the root level of node_modules. I had to reload my project window aswell to get typescript to play nice with vscode. This might cause problems however if the version you install as a direct dependency is incompatible with your version of @mui/material, so be careful if you take this approach.

In your case, it might be better to just map @mui/system directly to the nested dependency in your root level tsconfig.json file:

"compilerOptions": {
    "baseUrl": ".",
    "paths:": {
        "@mui/system": "@mui/material/node_modules/@mui/system"
    }
}
Lordsandladies answered 27/9, 2022 at 1:21 Comment(3)
Adding @mui/system in the path did not work, but installing @mui/system directly as a dev dependency did. Thank you so much @minnow!Charmion
I don't think this is a perfect solution. There might be the rare case where your project relies on two transitive dependencies of different versions. It's also a pain to make sure that the peer dependency you install is always the correct version. I feel like there must be a better solution, I'm still not absolutely sure why this occurs but if there's some way to flatten peer dependencies with your package manager so there aren't any nested node_modules I would probably recommend that. If I come across a better solution I will let you knowLordsandladies
@GeorgeK's answer should be the solution to this problem, it really helps! Thanks!Macaluso
P
7

This error usually indicates there are multiple versions of a dependency in the project, e.g. one defined in the package.json of a package, another specified as a dependency in root level package.json. You can verify this by running: yarn why package-name, e.g. yarn why @mui/system. In case of mismatching versions you'd see:

├─ my-repo@workspace:packages/react-components [c0f3f]
│  └─ @mui/system@npm:5.10.4 [9e221] (via npm:5.10.4 [9e221])
│
├─ my-repo@workspace:packages/react-components
│  └─ @mui/system@npm:5.10.4 [9e221] (via npm:5.10.4 [9e221])
│
├─ @mui/material@npm:5.10.4
│  └─ @mui/system@npm:5.11.16 (via npm:^5.10.4)
│
└─ @mui/material@npm:5.10.4 [9e221]
   └─ @mui/system@npm:5.11.16 [478da] (via npm:^5.10.4 [478da])

Notice how two first entries are using @mui/system 5.10.4, while the latter two use 5.11.16.

To fix it, update the mismatching version you defined in "dependencies" in your package.json to match the one required another library.

Here: yarn workspace @my-repo/react-components add @mui/[email protected]. Confirm whether it has taken effect by running yarn info package-name again.

Povertystricken answered 6/4, 2023 at 11:50 Comment(0)
L
5

I had this issue using mui styled with pnpm in a monorepo setting. After some digging it seems to be caused by typescript not playing well with nested transitive dependencies.

Here are some related issues on github where people discuss the root of the problem and pose some solutions:

Typescript Issue #36800

Typescript Issue #30858

I couldn't find a convenient solution that worked for pnpm, besides configuring nodelinker=hoisted, which defeats the purpose of using pnpm in the first place.

EDIT

It seems that installing @mui/system as a direct dependency worked, since @mui/system is now at the root level of node_modules. I had to reload my project window aswell to get typescript to play nice with vscode. This might cause problems however if the version you install as a direct dependency is incompatible with your version of @mui/material, so be careful if you take this approach.

In your case, it might be better to just map @mui/system directly to the nested dependency in your root level tsconfig.json file:

"compilerOptions": {
    "baseUrl": ".",
    "paths:": {
        "@mui/system": "@mui/material/node_modules/@mui/system"
    }
}
Lordsandladies answered 27/9, 2022 at 1:21 Comment(3)
Adding @mui/system in the path did not work, but installing @mui/system directly as a dev dependency did. Thank you so much @minnow!Charmion
I don't think this is a perfect solution. There might be the rare case where your project relies on two transitive dependencies of different versions. It's also a pain to make sure that the peer dependency you install is always the correct version. I feel like there must be a better solution, I'm still not absolutely sure why this occurs but if there's some way to flatten peer dependencies with your package manager so there aren't any nested node_modules I would probably recommend that. If I come across a better solution I will let you knowLordsandladies
@GeorgeK's answer should be the solution to this problem, it really helps! Thanks!Macaluso
F
3

I was facing the same issue with my nextjs and monorepo project using pnpm. I've found out a solution.

If you are using MUI, then you need to add this in the root file of your project.

import type {} from "@mui/system";
import type {} from "@emotion/styled";

If you are using Nextjs, then the root file would be layout.tsx file. If you are using React with vite, then I think the root file would be main.ts file.

If you don't want to add the above code snippet to the root of your file, you can simply create typings.d.ts file in the root and add the above code snippet there and you are good to go.

Note: I only tested this on my Nextjs 14 project and monorepo using turbo.

This is the GitHub repository and GitHub discussion if you want to see more detail.

FYI: This solution should be valid for all the packages. This is not limited to just Material UI (MUI).

What is the problem: Main issue is pnpm, which are installing packages as symlinks instead of copying files. Then Typescript follows the symlink and finds out the referenced file is out of the project root, which triggers the error.

Why we are importing type declartions? I think it seems TypeScript to find desired type declarations.

Fruitarian answered 28/5, 2024 at 11:53 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.