You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MUI中基于SCSS类的可复用TextField组件类型错误排查

解决MUI TextField封装SCSS类的类型错误

问题背景

要封装MUI的TextField为可复用组件,要求使用SCSS模块化类而非styled-components,但封装后出现类型不兼容错误。

非复用版本代码

<InputField
  id="<id_name>"
  label="<label>"
  variant="outlined"
  inputRef={inputRef}
  value={value}
  onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
    setValue(e.target.value)
  }}
  InputProps={{
    classes: {
      root: styles.search__field,  // 标准模块化SCSS类
      notchedOutline: styles.search__field, // 标准模块化SCSS类
    },
  }}
  InputLabelProps={{
    classes: {
      shrink: styles.search__label__focused, // 标准模块化SCSS类
    },
  }}
/>

尝试的复用组件代码

import { TextField, type TextFieldProps } from "@mui/material"

type InputFieldProps = {
  rootClass: string
  borderClass: string
  shrinkLabelClass: string
} & TextFieldProps

const InputField = ({
  rootClass,
  borderClass,
  shrinkLabelClass,
  InputProps,
  InputLabelProps,
  ...restProps
}: InputFieldProps) => {
  return (
    <TextField
      {...restProps}
      InputProps={{
        classes: {
          root: rootClass,
          notchedOutline: borderClass,
        },
      }}
      InputLabelProps={{
        classes: {
          shrink: shrinkLabelClass,
        },
      }}
    />
  )
}

出现的错误信息

The TextField is a convenience wrapper for the most common cases (80%). It cannot be all things to all people, otherwise the API would grow out of control.

Type '{ InputProps: { classes: { root: string; notchedOutline: string; }; }; InputLabelProps: { classes: { shrink: string; }; }; onChange?: ChangeEventHandler<HTMLTextAreaElement | HTMLInputElement> | undefined; ... 284 more ...; onTransitionEndCapture?: TransitionEventHandler<...> | undefined; }' is not assignable to type 'IntrinsicAttributes & TextFieldProps'.
The types of 'InputProps.classes' are incompatible between these types.
Type '{ root: string; notchedOutline: string; }' is not assignable to type 'Partial'.
Property 'notchedOutline' does not exist on type 'Partial'.ts(2322)

错误原因

  1. 类型不匹配:TextField的InputProps.classes默认对应InputClasses类型,而notchedOutline是OutlinedInputClasses特有的属性,直接添加会触发类型检查错误。
  2. 覆盖用户传入的Props:当前写法直接替换了InputProps和InputLabelProps,没有合并用户可能传入的额外配置,同时类型定义也没有考虑到不同输入变体的类类型。

解决方案

步骤1:导入正确的类类型

从MUI的具体组件导入对应的类类型,匹配outlined变体的需求:

import { TextField, type TextFieldProps } from "@mui/material";
import type { OutlinedInputClasses } from "@mui/material/OutlinedInput";
import type { InputLabelClasses } from "@mui/material/InputLabel";

步骤2:调整Props类型定义

自定义Props的类属性对应正确的类型,同时允许用户传入额外的InputProps和InputLabelProps:

type InputFieldProps = {
  rootClass: OutlinedInputClasses["root"];
  borderClass: OutlinedInputClasses["notchedOutline"];
  shrinkLabelClass: InputLabelClasses["shrink"];
} & Omit<TextFieldProps, "InputProps" | "InputLabelProps"> & {
  InputProps?: Omit<TextFieldProps["InputProps"], "classes"> & {
    classes?: Partial<OutlinedInputClasses>;
  };
  InputLabelProps?: Omit<TextFieldProps["InputLabelProps"], "classes"> & {
    classes?: Partial<InputLabelClasses>;
  };
};

步骤3:合并自定义类与用户传入的类

在组件内部合并自定义的SCSS类和用户可能传入的额外类,避免覆盖:

const InputField = ({
  rootClass,
  borderClass,
  shrinkLabelClass,
  InputProps = {},
  InputLabelProps = {},
  ...restProps
}: InputFieldProps) => {
  return (
    <TextField
      {...restProps}
      variant="outlined" // 固定为outlined变体,确保类属性生效
      InputProps={{
        ...InputProps,
        classes: {
          root: rootClass,
          notchedOutline: borderClass,
          ...InputProps.classes, // 合并用户传入的额外类
        },
      }}
      InputLabelProps={{
        ...InputLabelProps,
        classes: {
          shrink: shrinkLabelClass,
          ...InputLabelProps.classes, // 合并用户传入的额外类
        },
      }}
    />
  );
};

说明

  • 固定variant="outlined":因为notchedOutline只在outlined变体下存在,确保组件逻辑与类属性匹配。
  • 合并类配置:用户传入的classes会覆盖自定义的同名类,保留灵活性。
  • 精确类型约束:通过OutlinedInputClasses和InputLabelClasses确保类属性的类型正确性。

内容的提问来源于stack exchange,提问作者Cemal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 00:02:50