开发者问题收集

Material UI React Typescript - 扩展主题颜色 - 无法修复 Typescript 问题

2021-05-26
3372

我是 Typescript 的新手,非常困惑,有人能帮忙吗? 所以我在 React 项目中将 Material-ui 与 Typescript 结合使用。如果有人想以“正确”的方式添加新颜色,他们必须将其添加到主题中:

const theme = createMuiTheme({
  palette: {
    primary: {
      main: blue[400]
    },
    secondary: {
      main: green[500]
    },
    neutral: {
      main: "#abcdef" // <-- NEW COLOR
    }
  }
})

然后,每当您想使用主题时,都可以在 ThemeProvider 包装器组件中使用它。直接来自文档。但是,如果受害者也试图使用 Typescript,他们必须扩展 Palette 接口(文档再次以此为例)..

declare module "@material-ui/core/styles/createPalette" {
  interface Palette {
    neutral: Palette["primary"]
  }
  interface PaletteOptions {
    neutral: PaletteOptions["primary"]
  }
}

同样,只是从文档中复制/粘贴。似乎有道理!现在 Typescript 不再抱怨调色板中的新属性。现在,是时候试试我的新颜色了!但是,当我尝试在组件中使用它时:

<IconButton color="neutral" onClick={onClose}> {/* big problem!! */}
   <CloseIcon />
</IconButton>

这就是我感到困惑的地方。Typescript 会抱怨!我的意思是,我想抱怨是 Typescript 的工作,但我不知道如何处理它。'color' 上有一个红色波浪线,因为 color prop 的类型没有“netural”选项。

红色波浪线的图片

但当然,我是新手,我可能会错过一些显而易见的东西。 因此,就像我说的,组件的 props 被定义为“类型”,而不是接口或类似的东西,而“颜色”是其中的另一种类型,它只接受某些刺痛,我只需要让它识别“中性”,但我不知道。有办法吗?(不使用 ts-ignore)

{/* 
// @ts-ignore */}
<IconButton color="neutral" ...

(不想这样做)

我觉得如果我要以“正确”的方式使用颜色,应该有一个简单的解决方法……但我只是没有看到它。请帮忙!!

2个回答

请记住,您不能将 color 属性的任意值传递给 IconButton 以及任何其他material-ui的 Button 。只能重新定义现有的主题颜色: primarysecondary 。此行为是 硬编码 (4.x),并且在可预见的 未来 (5.x)内不会发生变化。

className/classes 覆盖,如所提议的Barryman9000。


至于类型,我认为没有简单的方法来覆盖 4.x 的 PropTypes.Color 类型定义。但从 5.x(@next) 开始,您可以通过合并 IconButtonPropsColorOverrides 接口来 扩展或限制 IconButtoncolor prop 可接受值:

interface IconButtonPropsColorOverrides {
  neutral: true // allow `neutral` to be used as a color prop value
  primary: false // forbid using `primary`
}

但您仍必须为这些值实现实际的行为逻辑。它们不会立即起作用(截至当前(2021-05)@next 代码的状态)

aleksxor
2021-05-26

我遇到过这种情况。我认为问题在于您只是扩展了主题对象,但 <IconButton /> 组件的 color prop 属于 PropTypes.Color 类型,其中 Color 是联合类型,并且仅接受这四个值

export namespace PropTypes {
  type Color = 'inherit' | 'primary' | 'secondary' | 'default';
}

我使用了几种不同的方法来解决这个问题。使用 useTheme() 钩子,您可以从组件中的调色板访问 neutral 主题颜色,也可以创建样式化组件并从那里访问调色板

在您的组件中

const MyComponent = () => {
  const { palette } = useTheme();

  return (
    <IconButton
      color={palette.neutral.main}
    >...</IconButton>)
}

styled-component

const MyStyledComponent = styled(IconButton)(({ theme }) => ({
  color: theme.palette.neutral.main
}));
Duderino9000
2021-05-26