React TS集成JS版Material UI模板报错求助
React+TypeScript集成Material UI JS模板的类型错误解决
我是业余开发者,正在用React+TypeScript搭建网站,找到一个免费Material UI模板,它基于JavaScript编写,集成到现有TS代码时出现兼容问题。
涉及代码
1. login.tsx文件
import { useState } from "react"; // react-router-dom components import { Link } from "react-router-dom"; // @mui material components import Card from "@mui/material/Card"; import Switch from "@mui/material/Switch"; import Grid from "@mui/material/Grid"; import MuiLink from "@mui/material/Link"; // @mui icons import FacebookIcon from "@mui/icons-material/Facebook"; import GitHubIcon from "@mui/icons-material/GitHub"; import GoogleIcon from "@mui/icons-material/Google"; // Material Kit 2 React components import MKBox from "../newcomponents/MKBox/"; import MKTypography from "../newcomponents/MKTypography"; import MKInput from "../newcomponents/MKInput"; import MKButton from "../newcomponents/MKButton"; import SimpleFooter from "../examples/Footers/SimpleFooter"; // Images import bgImage from "assets/images/bg-sign-in-basic.jpeg"; import linearGradient from "assets/theme/functions/linearGradient"; const Login: React.FC = () => { const [rememberMe, setRememberMe] = useState<boolean>(false); const handleSetRememberMe = () => setRememberMe(!rememberMe); return ( <> <MKBox position="absolute" top={0} left={0} zIndex={1} width="100%" minHeight="100vh" sx={{ backgroundImage: ({ functions: { linearGradient, rgba }, palette: { gradients }, }) => `${linearGradient( rgba(gradients.dark.main, 0.6), rgba(gradients.dark.state, 0.6) )}, url(${bgImage})`, backgroundSize: "cover", backgroundPosition: "center", backgroundRepeat: "no-repeat", }} /> <MKBox px={1} width="100%" height="100vh" mx="auto" position="relative" zIndex={2}> <Grid container spacing={1} justifyContent="center" alignItems="center" height="100%"> <Grid item xs={11} sm={9} md={5} lg={4} xl={3}> <Card> <MKBox variant="gradient" bgColor="info" borderRadius="lg" coloredShadow="info" mx={2} mt={-3} p={2} mb={1} textAlign="center" > <MKTypography variant="h4" fontWeight="medium" color="white" mt={1}> Sign in </MKTypography> <Grid container spacing={3} justifyContent="center" sx={{ mt: 1, mb: 2 }}> <Grid item xs={2}> <MKTypography component={MuiLink} href="#" variant="body1" color="white"> <FacebookIcon color="inherit" /> </MKTypography> </Grid> <Grid item xs={2}> <MKTypography component={MuiLink} href="#" variant="body1" color="white"> <GitHubIcon color="inherit" /> </MKTypography> </Grid> <Grid item xs={2}> <MKTypography component={MuiLink} href="#" variant="body1" color="white"> <GoogleIcon color="inherit" /> </MKTypography> </Grid> </Grid> </MKBox> <MKBox pt={4} pb={3} px={3}> <MKBox component="form" role="form"> <MKBox mb={2}> <MKInput type="email" label="Email" fullWidth /> </MKBox> <MKBox mb={2}> <MKInput type="password" label="Password" fullWidth /> </MKBox> <MKBox display="flex" alignItems="center" ml={-1}> <Switch checked={rememberMe} onChange={handleSetRememberMe} /> <MKTypography variant="button" fontWeight="regular" color="text" onClick={handleSetRememberMe} sx={{ cursor: "pointer", userSelect: "none", ml: -1 }} > Remember me </MKTypography> </MKBox> <MKBox mt={4} mb={1}> <MKButton variant="gradient" color="info" fullWidth> sign in </MKButton> </MKBox> <MKBox mt={3} mb={1} textAlign="center"> <MKTypography variant="button" color="text"> Don't have an account?{" "} <MKTypography component={Link} to="/authentication/sign-up/cover" variant="button" color="info" fontWeight="medium" textGradient > Sign up </MKTypography> </MKTypography> </MKBox> </MKBox> </MKBox> </Card> </Grid> </Grid> </MKBox> {/* <MKBox width="100%" position="absolute" zIndex={2} bottom="1.625rem"> <SimpleFooter light /> </MKBox> */} </> ); }; export default Login;
2. 未修改的MKBox组件(MKBox.js)
/** ========================================================= * Material Kit 2 React - v2.1.0 ========================================================= * Product Page: https://www.creative-tim.com/product/material-kit-react * Copyright 2023 Creative Tim (https://www.creative-tim.com) Coded by www.creative-tim.com ========================================================= * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. */ import { forwardRef } from "react"; // prop-types is a library for typechecking of props import PropTypes from "prop-types"; // Custom styles for MKBox import MKBoxRoot from "./MKBoxRoot"; const MKBox = forwardRef( ({ variant, bgColor, color, opacity, borderRadius, shadow, coloredShadow, ...rest }, ref) => ( <MKBoxRoot {...rest} ref={ref} ownerState={{ variant, bgColor, color, opacity, borderRadius, shadow, coloredShadow }} /> ) ); // Setting default values for the props of MKBox MKBox.defaultProps = { variant: "contained", bgColor: "transparent", color: "dark", opacity: 1, borderRadius: "none", shadow: "none", coloredShadow: "none", }; // Type checking props for the MKBox MKBox.propTypes = { variant: PropTypes.oneOf(["contained", "gradient"]), bgColor: PropTypes.string, color: PropTypes.string, opacity: PropTypes.number, borderRadius: PropTypes.string, shadow: PropTypes.string, coloredShadow: PropTypes.oneOf([ "primary", "secondary", "info", "success", "warning", "error", "light", "dark", "none", ]), }; export default MKBox;
3. MKBoxRoot.js文件
/** ========================================================= * Material Kit 2 React - v2.1.0 ========================================================= * Product Page: https://www.creative-tim.com/product/material-kit-react * Copyright 2023 Creative Tim (https://www.creative-tim.com) Coded by www.creative-tim.com ========================================================= * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. */ // @mui material components import Box from "@mui/material/Box"; import { styled } from "@mui/material/styles"; export default styled(Box)(({ theme, ownerState }) => { const { palette, functions, borders, boxShadows } = theme; const { variant, bgColor, color, opacity, borderRadius, shadow, coloredShadow } = ownerState; const { gradients, grey, white } = palette; const { linearGradient } = functions; const { borderRadius: radius } = borders; const { colored } = boxShadows; const greyColors = { "grey-100": grey[100], "grey-200": grey[200], "grey-300": grey[300], "grey-400": grey[400], "grey-500": grey[500], "grey-600": grey[600], "grey-700": grey[700], "grey-800": grey[800], "grey-900": grey[900], }; const validGradients = [ "primary", "secondary", "info", "success", "warning", "error", "dark", "light", ]; const validColors = [ "transparent", "white", "black", "primary", "secondary", "info", "success", "warning", "error", "light", "dark", "text", "grey-100", "grey-200", "grey-300", "grey-400", "grey-500", "grey-600", "grey-700", "grey-800", "grey-900", ]; const validBorderRadius = ["xs", "sm", "md", "lg", "xl", "xxl", "section"]; const validBoxShadows = ["xs", "sm", "md", "lg", "xl", "xxl", "inset"]; // background value let backgroundValue = bgColor; if (variant === "gradient") { backgroundValue = validGradients.find((el) => el === bgColor) ? linearGradient(gradients[bgColor].main, gradients[bgColor].state) : white.main; } else if (validColors.find((el) => el === bgColor)) { backgroundValue = palette[bgColor] ? palette[bgColor].main : greyColors[bgColor]; } else { backgroundValue = bgColor; } // color value let colorValue = color; if (validColors.find((el) => el === color)) { colorValue = palette[color] ? palette[color].main : greyColors[color]; } // borderRadius value let borderRadiusValue = borderRadius; if (validBorderRadius.find((el) => el === borderRadius)) { borderRadiusValue = radius[borderRadius]; } // boxShadow value let boxShadowValue = "none"; if (validBoxShadows.find((el) => el === shadow)) { boxShadowValue = boxShadows[shadow]; } else if (coloredShadow) { boxShadowValue = colored[coloredShadow] ? colored[coloredShadow] : "none"; } return { opacity, background: backgroundValue, color: colorValue, borderRadius: borderRadiusValue, boxShadow: boxShadowValue, }; });
抛出的错误信息
- 属性类型不匹配:
Type '{ position: string; top: number; left: number; zIndex: number; width: string; minHeight: string; sx: { backgroundImage: ({ functions: { linearGradient, rgba }, palette: { gradients }, }: { functions: { linearGradient: any; rgba: any; }; palette: { gradients: any; }; }) => string; backgroundSize: string; backgroundPo...' is not assignable to type 'IntrinsicAttributes & RefAttributes<any>'. Property 'position' does not exist on type 'IntrinsicAttributes & RefAttributes<any>'
- 子元素类型不匹配:
Type '{ children: Element; px: number; width: string; height: string; mx: string; position: string; zIndex: number; }' is not assignable to type 'IntrinsicAttributes & RefAttributes<any>'. Property 'children' does not exist on type 'IntrinsicAttributes & RefAttributes<any>'
- 隐式any类型:
Binding element 'linearGradient' implicitly has an 'any' type
解决方案
1. 为MKBox添加TypeScript类型定义
将MKBox.js重命名为MKBox.tsx,定义组件Props并继承MUI Box的属性:
import { forwardRef, PropsWithChildren } from "react"; import { BoxProps } from "@mui/material/Box"; import MKBoxRoot from "./MKBoxRoot"; // 自定义MKBox属性类型 type MKBoxProps = BoxProps & { variant?: "contained" | "gradient"; bgColor?: string; color?: string; opacity?: number; borderRadius?: string; shadow?: string; coloredShadow?: "primary" | "secondary" | "info" | "success" | "warning" | "error" | "light" | "dark" | "none"; }; const MKBox = forwardRef<HTMLDivElement, PropsWithChildren<MKBoxProps>>( ({ variant = "contained", bgColor = "transparent", color = "dark", opacity = 1, borderRadius = "none", shadow = "none", coloredShadow = "none", ...rest }, ref) => ( <MKBoxRoot {...rest} ref={ref} ownerState={{ variant, bgColor, color, opacity, borderRadius, shadow, coloredShadow }} /> ) ); export default MKBox;
2. 为MKBoxRoot添加类型定义
将MKBoxRoot.js重命名为MKBoxRoot.tsx,明确theme和ownerState的类型:
import Box from "@mui/material/Box"; import { styled, Theme } from "@mui/material/styles"; import { MKBoxProps } from "./MKBox"; type MKBoxRootProps = { theme: Theme; ownerState: Omit<MKBoxProps, keyof BoxProps>; }; export default styled(Box)(({ theme, ownerState }: MKBoxRootProps) => { const { palette, functions, borders, boxShadows } = theme; const { variant, bgColor, color, opacity, borderRadius, shadow, coloredShadow } = ownerState; const { gradients, grey, white } = palette; const { linearGradient } = functions; const { borderRadius: radius } = borders; const { colored } = boxShadows; const greyColors = { "grey-100": grey[100], "grey-200": grey[200], "grey-300": grey[300], "grey-400": grey[400], "grey-500": grey[500], "grey-600": grey[600], "grey-700": grey[700], "grey-800": grey[800], "grey-900": grey[900], }; const validGradients = [ "primary", "secondary", "info", "success", "warning", "error", "dark", "light", ]; const validColors = [ "transparent", "white", "black", "primary", "secondary", "info", "success", "warning", "error", "light", "dark", "text", "grey-100", "grey-200", "grey-300", "grey-400", "grey-500", "grey-600", "grey-700", "grey-800", "grey-900", ]; const validBorderRadius = ["xs", "sm", "md", "lg", "xl", "xxl", "section"]; const validBoxShadows = ["xs", "sm", "md", "lg", "xl", "xxl", "inset"]; // background value let backgroundValue = bgColor; if (variant === "gradient") { backgroundValue = validGradients.find((el) => el === bgColor) ? linearGradient(gradients[bgColor as keyof typeof gradients].main, gradients[bgColor as keyof typeof gradients].state) : white.main;
相关产品推荐
相关产品推荐

