首页 > 解决方案 > 扩展 MUI 组件会导致有关“css”属性丢失的 TS 错误

问题描述

我们用我们的自定义组件(MySnackbarContent)扩展了 SnackbarContent 组件:

export interface MySnackbarContentProps extends Omit<SnackbarContentProps, 'variant'> {
  variant?: MyCustomVariant;
  type?: MyCustomType;
  banner?: boolean;
  // ...
}

const MySnackbarContent = forwardRef<HTMLElement, MySnackbarContentProps>(props: MySnackbarContentProps, ref) => {
  const { variant = 'normal', type = 'default', banner = false, ...other } = props;
  const className = ...;

  return <SnackbarContent ref={ref} className={className} {...other} />
}

这是我在使用自定义 SnackbarContent 组件时遇到的错误:

类型 '{ type: "error" | 中缺少属性 'css' “默认” | “成功” | 不明确的; 消息:字符串;动作:元素;}' 但在 'Pick<MySnackbarContentProps, "hidden" | 类型中是必需的 “风格” | "选择" | “插槽” | “标题” | "类名" | “类” | “内部参考” | “默认检查” | “默认值” | ... 258 更多... | “动作点击处理程序”>'。

我不明白为什么css这里的属性是一个问题,因为我们没有使用情感或样式组件(我们使用的是 JSS)。

奇怪的是,当我删除所有类型时都会正确检查forwardRef.

缓解此问题的一种可能方法是添加css属性MySnackbarContentProps并将其设置为:css?: null. 出于某种原因,css属性是必需的属性。不是 100% 确定为什么会出现这种情况。我在这里想念什么?

编辑:根本原因的解释

试图了解根本原因时,有三个部分在起作用。

首先,Typescript 允许扩充任何类型,扩充的结果将合并不同定义中的属性。例如,下面的代码:

interface Person {
  name: string;
}

interface Person {
  age: number;
}

将与编写以下内容相同:

interface Person {
  name: string;
  age: number
}

操场

这种扩充不需要在同一个模块/文件中;因此,项目中的任何模块(包括 node_modules)都可以扩充另一个模块中的任何类型)。

其次,Material UI 允许将所有 DOM 属性传递给它的许多组件。因此,它本质上是在许多组件中扩展基础React.DOMAttributes<T>(例如 Paper extends )。React.DOMAttributes<HTMLDivElement>

对我来说,我能够找到问题,因为我知道这css是 Storybook 使用的 的属性emotion;因此,我深入研究了情绪的作用并发现了以下内容:https ://github.com/emotion-js/emotion/blob/31e610f2385d5a3dfd532b31f743e5f6b9fee43b/packages/react/types/index.d.ts#L99

React.DOMAttributes<T>因此,通过向其添加可选 css属性来增强情感。如果任何类型从该类型扩展,它们将有权访问css属性。这足以让我确定罪魁祸首。该库正在导出一个打算在 Storybook 中使用的实用程序(一些 Storybook 功能是从这些实用程序导入的)。从输出中删除该组件解决了这个问题。如果您使用的是 Storybook,请检查输出的包是否使用了任何 Storybook 组件。

我没有调查的一件事是为什么css即使情感将道具作为可选属性传递也是强制性属性。

标签: reactjstypescriptmaterial-ui

解决方案


推荐阅读