首页 > 解决方案 > 扩展 Material UI ListItem 的正确方法是什么?

问题描述

我正在使用 TypeScript 3.4.5 和 Material UI 4.2 以及以下代码:

interface MyItemProps {
    name: string;
    value: string;
}

function Item({ name, value, ...props }: ListItemProps<'li', MyItemProps>): ReactElement {
    return (
        <ListItem {...props} className="item">
            <ListItemText primary={name} secondary={value || '-'} />
        </ListItem>
    );
}

我收到Type 'boolean' is not assignable to type 'true'错误。为什么?

我一直在研究 的类型定义ListItem,但我不知道发生了什么:

export interface ListItemTypeMap<P, D extends React.ElementType> {
  props: P & {
    alignItems?: 'flex-start' | 'center';
    autoFocus?: boolean;
    button?: boolean;
    ContainerComponent?: React.ElementType<React.HTMLAttributes<HTMLDivElement>>;
    ContainerProps?: React.HTMLAttributes<HTMLDivElement>;
    dense?: boolean;
    disabled?: boolean;
    disableGutters?: boolean;
    divider?: boolean;
    focusVisibleClassName?: string;
    selected?: boolean;
  };
  defaultComponent: D;
  classKey: ListItemClassKey;
}

declare const ListItem: OverridableComponent<ListItemTypeMap<{ button?: false }, 'li'>> &
  ExtendButtonBase<ListItemTypeMap<{ button: true }, 'div'>>;

export type ListItemClassKey =
  | 'root'
  | 'container'
  | 'focusVisible'
  | 'default'
  | 'dense'
  | 'disabled'
  | 'divider'
  | 'gutters'
  | 'button'
  | 'secondaryAction'
  | 'selected';

export type ListItemProps<D extends React.ElementType = 'li', P = {}> = OverrideProps<
  ListItemTypeMap<P, D>,
  D
>;

export default ListItem;

我唯一想到的是“类型扩大”,但我真的不知道发生了什么以及为什么。

有人可以解释发生了什么吗?最重要的是,扩展 Material UI 组件的正确方法是什么?

标签: javascriptreactjstypescriptmaterial-ui

解决方案


在 material-ui github 上,这似乎是一个成熟的问题。显然,它源于使用布尔值来进行工会歧视——我对 TS 还是新手,所以只能大致了解这意味着什么!

我从这些线程中找到的最干净的方法buttonany通过将buttontrue 直接转换为ListItem

interface MyItemProps {
    name: string;
    value: string;
}

type MyListItem = ListItemProps<"li", MyItemProps>;

function Item({ name, value, button, ...props }: MyListItem): ReactElement {
    return (
        <ListItem {...props} className="item" button={button as true}>
            <ListItemText primary={name} secondary={value || '-'} />
        </ListItem>
    );
}

推荐阅读