带参数的Styled Base UI组件触发TypeScript错误,需何种类型修改修复?
原始TSX代码
import React from "react"; import BaseButton from "@mui/base/Button"; import styled from "@emotion/styled"; export const enum BUTTON_TYPE { MAIN = "main", LINK = "link", } const Button = ({ text, type, }: { text: string; type: BUTTON_TYPE; }) => { return ( <StyledButton type={type}> {text} </StyledButton> ); }; const getBorderColor = (type: BUTTON_TYPE): string => { if(type === BUTTON_TYPE.MAIN) { return "#abcabc"; } else { return "#cbacba"; } }; const StyledButton = styled(BaseButton)<{ type: BUTTON_TYPE; }>` border: 1px solid ${({ type }) => getBorderColor(type)}; `; export default Button;
触发的TypeScript错误
src/modules/Button/Button.tsx:18:6 - error TS2745: This JSX tag's 'children' prop expects type 'never' which requires multiple children, but only a single child was provided. 18 <StyledButton type={type}> ~~~~~~~~~~~~ src/modules/Button/Button.tsx:18:19 - error TS2322: Type 'import("C:/ez/DS13/src/modules/Button/Button2").BUTTON_TYPE' is not assignable to type 'never'. 18 <StyledButton type={type}>
修复方案
错误根源是自定义styled组件时,没有把BaseButton自带的Props类型和自定义的type属性类型合并,导致TypeScript丢失了组件原生的children、按钮属性等类型信息,同时无法识别你传入的type属性。
步骤1:导入BaseButton的原生Props类型
先从MUI的BaseButton里导入它原本的Props类型:
import type { ButtonProps } from '@mui/base/Button';
步骤2:合并类型定义
定义StyledButton时,把自定义的type属性和ButtonProps交叉合并,确保保留原生组件的所有类型:
const StyledButton = styled(BaseButton)<ButtonProps & { type: BUTTON_TYPE }>` border: 1px solid ${({ type }) => getBorderColor(type)}; `;
(可选)避免自定义属性传到DOM元素
如果不想让自定义的type属性被传递到底层的<button>DOM标签上,可以加个过滤规则:
const StyledButton = styled(BaseButton, { // 只传递除了type之外的属性给原生按钮 shouldForwardProp: (prop) => prop !== 'type' })<ButtonProps & { type: BUTTON_TYPE }>` border: 1px solid ${({ type }) => getBorderColor(type)}; `;
完整修复后的代码
import React from "react"; import BaseButton from "@mui/base/Button"; import type { ButtonProps } from '@mui/base/Button'; import styled from "@emotion/styled"; export const enum BUTTON_TYPE { MAIN = "main", LINK = "link", } const Button = ({ text, type, }: { text: string; type: BUTTON_TYPE; }) => { return ( <StyledButton type={type}> {text} </StyledButton> ); }; const getBorderColor = (type: BUTTON_TYPE): string => { if(type === BUTTON_TYPE.MAIN) { return "#abcabc"; } else { return "#cbacba"; } }; const StyledButton = styled(BaseButton, { shouldForwardProp: (prop) => prop !== 'type' })<ButtonProps & { type: BUTTON_TYPE }>` border: 1px solid ${({ type }) => getBorderColor(type)}; `; export default Button;
内容的提问来源于stack exchange,提问作者Csati
相关产品推荐
相关产品推荐

