开发者问题收集

Typescript 模块增强不起作用:类型“PaletteColorOptions”上不存在属性“main”

2021-08-19
8269

我一直在研究 Material-UI,并尝试在整个调色板中使用颜色系统。虽然它在运行时运行正常,但在编译时似乎出现了一些问题。有人能帮我解决以下错误吗:

错误:

Property 'main' does not exist on type 'PaletteColorOptions'.
Property 'main' does not exist on type 'Partial'.(2339)

这里还有 stackblitz: https://stackblitz.com/edit/react-up6bjl-hx1bbh?file=demo.tsx

代码:

import * as React from 'react';
import {
  createTheme,
  Theme,
  ThemeProvider,
  PaletteOptions
} from '@material-ui/core/styles';

import Button from '@material-ui/core/Button';

declare module '@material-ui/core/styles' {
  interface SimplePaletteColorOptions {
    lighter?: string;
    darker?: string;
  }

  interface PaletteColor {
    lighter?: string;
    darker?: string;
  }
}

const Default = () : PaletteOptions => {

  return {
    primary: {
      lighter: '#ddd',
      light: '#ddd',
      main: '#ddd',
      dark: '#ddd',
      darker: '#ddd'
    },
  };
};

export default function CustomColor() {
  const defaultColors = Default();
  
  const palette: PaletteOptions = {
    ...defaultColors,
    divider: defaultColors.primary?.main, // error in compile. Cannot find 'main'
  };

  const theme: Theme = createTheme({
    palette
  });

  console.log(theme.palette.primary.light);

  return (
    <ThemeProvider theme={theme}>
      <Button color="primary" variant="contained">
        neutral
      </Button>
    </ThemeProvider>
  );
}
2个回答

TypeScript 错误与您的模块扩充无关。问题只是 defaultColors 属于 PaletteOptions 类型。 PaletteOptions 将 primary 定义为 PaletteColorOptions 类型。

以下是 PaletteColorOptions 的定义以及它所基于的类型:

export type PaletteColorOptions = SimplePaletteColorOptions | ColorPartial;

export interface SimplePaletteColorOptions {
  light?: string;
  main: string;
  dark?: string;
  contrastText?: string;
}

export type ColorPartial = Partial<Color>;

export interface Color {
  50: string;
  100: string;
  200: string;
  300: string;
  400: string;
  500: string;
  600: string;
  700: string;
  800: string;
  900: string;
  A100: string;
  A200: string;
  A400: string;
  A700: string;
}

因此,TypeScript 编译器知道 defaultColors.primary 要么 SimplePaletteColorOptions ColorPartial ,但它不知道是哪一个。然后,您将引用 defaultColors.primary.main ,但除非 defaultColors.primary 的类型为 SimplePaletteColorOptions ,否则不能保证存在。

您可以通过对 Default 函数使用更具体的返回类型来解决此问题,该函数让 TypeScript 知道 primary 的类型为 SimplePaletteColorOptions

interface DefaultPaletteOptions extends PaletteOptions {
  primary?: SimplePaletteColorOptions;
}
const Default = (): DefaultPaletteOptions => {
  return {
    primary: {
      lighter: "#ddd",
      light: "#ddd",
      main: "#ddd",
      dark: "#ddd",
      darker: "#ddd"
    }
  };
};

Edit TypeScript PaletteOptions

相关答案:

Ryan Cogswell
2021-08-19

要使自定义调色板颜色与 MUI 组件一起使用(即 <Button color={'neutral'}> ,您还需要扩充该组件模块:

declare module '@mui/material/Button' {
  interface ButtonPropsColorOverrides {
    neutral: true;
  }
}

但是,在非 MUI 组件中使用自定义主题值时,我仍然遇到 Property 'main' does not exist 问题。我通过将自定义颜色分配给其自己的类型 const,然后将 .main 明确分配给字符串来解决这个问题:

const selector: PaletteColor | undefined = theme.palette[color as keyof Palette] as PaletteColor;
const colorString: string = selector ? selector.main : 'inherit';

https://mui.com/material-ui/customization/palette/#non-palette-colors

Arajay
2024-03-25