material-ui
material-ui copied to clipboard
Using Next.js 13, some imports (particularly SxProps type) are causing TypeScript and `next build` to stall
Duplicates
- [X] I have searched the existing issues
Latest version
- [X] I have tested the latest version
Steps to reproduce 🕹
Link to live example: (N/A)
Steps:
- use
npx create-next-appto build a Next.js 13 project with TypeScript=yes, ESLint=yes, experimental app dir=yes - Create a new file (
- in my case this is an icon file) that imports
{ SxProps} from @mui/material(see below code example): - Run
next buildfrom terminal, and it will stall out on "Linting and checking validity of types". TypeScript in VSCode will also churn for a very long time or indefinitely, possibly because of some circular imports? A Shift ⌘ PRestart TypeScript Serversometimes fixes it. - Possibly related: https://github.com/vercel/next.js/issues/32314 - I have tried the experimental disable esm option (Next seems to not care), and the other
transpilePackagesoption (which Next doesn't even seem to recognize on 13 anymore?) to no avail.
In short, it seems that SxProps is maybe importing from the wrong place, or creating a circular import. If I copy out the type definition for SxProps, and instead try importing SystemStyleObject, it tries to import it from @mui/system which doesn't seem to be there:
import { SystemStyleObject } from "@mui/system";
type SxProps<Theme extends object = {}> =
| SystemStyleObject<Theme>
| ((theme: Theme) => SystemStyleObject<Theme>)
| ReadonlyArray<
boolean | SystemStyleObject<Theme> | ((theme: Theme) => SystemStyleObject<Theme>)
>;
But replacing any reference to SystemStyleObject<Theme> with any allows the project to build. If I continue down this rabbit hole, it seems like any types imported from @mui/system/styleFunctionSx causes this problem.
Current behavior 😯
Terminal just does this indefinitely, have to force kill it. It also stalls out in the Next -> Vercel deployment, and there are no build logs anywhere that I can see.
Expected behavior 🤔
It is maybe too much to ask, but
info - Generating static pages (3/3)
info - Finalizing page optimization
Route (app) Size First Load JS
─ ○ / 0 B 0 B
+ First Load JS shared by all 82.7 kB
├ chunks/17-f2d707dd60cbbe95.js 80.4 kB
├ chunks/main-app-75838474ac2d918f.js 216 B
└ chunks/webpack-bf40d3e2e2b9f54b.js 2.11 kB
Route (pages) Size First Load JS
┌ ○ /404 179 B 81.2 kB
├ λ /api/hello 0 B 81 kB
+ First Load JS shared by all 81 kB
├ chunks/main-7f0563c831689cf4.js 78.7 kB
├ chunks/pages/_app-5841ab2cb3aa228d.js 192 B
└ chunks/webpack-bf40d3e2e2b9f54b.js 2.11 kB
λ (Server) server-side renders at runtime (uses getInitialProps or getServerSideProps)
○ (Static) automatically rendered as static HTML (uses no initial props)
✨ Done in 10.87s.
Context 🔦
Not how this is affecting me, but project structure may help:
(This is a standard Next wizard built app, but nevertheless)
.next/
.vscode/
public/
src/
﹂app/
lib/
pages/api/hello.ts // stock, no changes
styles/
﹂colors/
﹂colors.types.ts
﹂icons/
﹂AircraftPrivateJetMd.tsx
appTheme.ts
// generated via: https://github.com/brandonscript/mui-svg-icons-generator
import * as React from "react";
import { CSSProperties } from "@mui/styles";
import { SvgIcon, SvgIconProps, SxProps } from "@mui/material";
// ^ the sadness
// import type { SxProps } from "@mui/system/styleFunctionSx/styleFunctionSx.d";
// ^ have had some success importing from here - I got it to compile just twice, but VSCode doesn't seem to know about this path, and it has failed every other time.
import { memo } from "react";
const SvgAircraftPrivateJetMd = (
props: SvgIconProps & { sx?: SxProps<CSSProperties> }
) => {
const { sx, ...other } = props;
const fontSize =
other.fontSize || sx?.fontSize || other?.style?.fontSize || undefined;
const sizeClassName = fontSize
? "PacificAviatorSvgIcon-sizeCustom"
: "PacificAviatorSvgIcon-sizeMd";
return (
<SvgIcon
fill="none"
xmlns="http://www.w3.org/2000/svg"
preserveAspectRatio="xMidYMid meet"
viewBox="0 0 30 30"
className={`PacificAviatorSvgIcon-AircraftPrivateJetIcon_md ${sizeClassName}`}
style={{
fill: "none",
}}
sx={{
...sx,
}}
{...other}
>
<path
d="M10.1 17.212a4.9 4.9 0 1 0 9.8 0 4.9 4.9 0 0 0-9.8 0ZM13.367 15.58h3.266M15 12.313V7.888M11.235 14.078 9.078 11.92M6.29 10.766a1.633 1.633 0 1 0 3.266 0 1.633 1.633 0 0 0-3.266 0ZM18.765 14.078l2.157-2.157M20.444 10.766a1.633 1.633 0 1 0 3.266 0 1.633 1.633 0 0 0-3.266 0Z"
stroke="currentColor"
strokeWidth={1.503}
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M18.163 20.953h6.908a2.178 2.178 0 0 0 2.178-2.177M2.751 18.776a2.177 2.177 0 0 0 2.178 2.177h6.913M12.822 7.888h4.356"
stroke="currentColor"
strokeWidth={1.503}
strokeLinecap="round"
strokeLinejoin="round"
/>
</SvgIcon>
);
};
const Memo = memo(SvgAircraftPrivateJetMd);
export default Memo;
// appTheme.ts
import { createTheme, responsiveFontSizes, Theme } from "@mui/material/styles";
const theme: Theme = createTheme({
palette: {
mode: "light",
},
components: {
// none
},
});
const compositeTheme = responsiveFontSizes((theme), {
factor: 1.25,
});
export default compositeTheme;
// colors.types.ts
import { Palette, PaletteOptions } from "@mui/material";
export interface ExtendedPalette<T extends Palette | PaletteOptions> {
brand?: T["primary"];
}
declare module "@mui/material/styles/createPalette" {
interface TypeBackground {
well?: string;
}
}
declare module "@mui/material/styles" {
interface Palette extends ExtendedPalette<Palette> {}
interface PaletteOptions extends ExtendedPalette<PaletteOptions> {}
}
// tsconfig.json
{
"compilerOptions": {
"baseUrl": "./src",
"target": "ESNext",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
appDir: true,
},
eslint: {
ignoreDuringBuilds: true,
},
};
module.exports = nextConfig
// package.json
{
"name": "next13-test",
"version": "2.0.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"@emotion/react": "^11.10.5",
"@emotion/styled": "^11.10.5",
"@mui/material": "^5.11.7",
"@mui/styled-engine": "^5.11.0",
"@mui/styles": "^5.11.7",
"@mui/system": "^5.11.7",
"@next/font": "^13.1.6",
"@types/node": "18.11.18",
"@types/react": "18.0.26",
"@types/react-dom": "18.0.10",
"eslint": "8.30.0",
"eslint-config-next": "^13.1.6",
"next": "^13.1.6",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"main": "app/page.tsx",
"devDependencies": {
"@babel/core": "^7.0.0",
"@types/react-syntax-highlighter": "^15.5.5",
"prettier": "^2.8.3",
"typescript": "^4.9.5",
"yarn": "^1.22.19"
}
}
Your environment 🌎
npx @mui/envinfo
npx: installed 2 in 1.512s
System:
OS: macOS 13.1
Binaries:
Node: 18.3.0 - ~/.local/share/nvm/v18.3.0/bin/node
Yarn: 1.22.19 - ~/Dev/next13-test/node_modules/.bin/yarn
npm: 8.11.0 - ~/.local/share/nvm/v18.3.0/bin/npm
Browsers:
Chrome: 109.0.5414.119 <- normally I use for dev, but this is a headless problem.
Edge: Not Found
Firefox: 107.0
Safari: 16.2
npmPackages:
@emotion/react: ^11.10.5 => 11.10.5
@emotion/styled: ^11.10.5 => 11.10.5
@mui/base: 5.0.0-alpha.116
@mui/core-downloads-tracker: 5.11.7
@mui/material: ^5.11.7 => 5.11.7
@mui/private-theming: 5.11.7
@mui/styled-engine: ^5.11.0 => 5.11.0
@mui/styles: ^5.11.7 => 5.11.7
@mui/system: ^5.11.7 => 5.11.7
@mui/types: 7.2.3
@mui/utils: 5.11.7
@types/react: 18.0.26 => 18.0.26
react: ^18.2.0 => 18.2.0
react-dom: ^18.2.0 => 18.2.0
typescript: ^4.9.5 => 4.9.5
Being struggling with the same error for days. I believe in my case it's related to the Autocomplete component
@brandonscript can you please create github repository that I can clone and test this out? I want to make sure that everything is set up exactly as in your repository.
@mnajdova hey Marija, sorry this took so long – a juggling a few things right now. Here you go: https://github.com/brandonscript/next13-mui-system-typescript-bug
Probably I've caught a similar issue when building lib with NX(vite).
When I've added:
type MyCmpProps = { sx?: SxProps<Theme>; ... }
It has caused the "Start generate declaration files..." step takes forever.
After some diving in I've found the reason is: "type SystemStyleObject"
It's not a genuinely proper fix but it works for me as for now:
- I've made a dirty fixed clone of "SystemStyleObject" and "SxProps". And used it where I need it.
import {CSSPseudoSelectorProps, CSSSelectorObjectOrCssVariables, SystemCssProperties} from "@mui/system/styleFunctionSx/styleFunctionSx";
export type SystemStyleObject<Theme extends object = {}> =
| SystemCssProperties<Theme>
| CSSPseudoSelectorProps<Theme>
| CSSSelectorObjectOrCssVariables<Theme>
| any // <---dirty hotfix
| null;
export type SxProps<Theme extends object = {}> =
| SystemStyleObject<Theme>
| ((theme: Theme) => SystemStyleObject<Theme>)
| ReadonlyArray<
boolean | SystemStyleObject<Theme> | ((theme: Theme) => SystemStyleObject<Theme>)
>;
@brandonscript Have you tried adding 'use client'; at the beginning of the files which are using mui?
@nikelborm sure did. I split it out into server components with nested client components.
I have the same issue but within a React (Vite) project: importing SxProps causes tsc to stall. My IDE self-imports it from '@mui/material' though (not from "@mui/system/styleFunctionSx"), but both options are causing the stall.
Also: if I pass to SxProps the optional generic, it doesn't stall anymore! [EDIT] the last sentence is incorrect. It didn't stall because I was passing a wrong generic causing a type signature mismatch. So if it fails, it doesn't stall [/EDIT]
Any clues?
you can use as a "reference" to existing "sx" property, for example:
import Button, { ButtonProps } from '@mui/material/Button'
const a: ButtonProps['sx'] = {}
This will solve it
you can use as a "reference" to existing "sx" property, for example:
import Button, { ButtonProps } from '@mui/material/Button' const a: ButtonProps['sx'] = {}This will solve it
As a workaround it worked fine for me, thanks! 👍
@d0whc3r we were having a similar issue with a CRA with Typescript project using MUI v6!!
You helped us pin the same issue we were experiencing when executing react-scripts build: importing SxProps directly from import { SxProps } from '@mui/system'; or even import { SxProps } from '@mui/materials/styles'; resulted in a memory leak!
The solution was to import sx's type directly from the MUI component, for instance SelectProps['sx'], ButtonProps['sx'] etc.... 😅
I hope MUI can fix the way they export their types...