我正在使用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组件的正确方法是什么?
答案 0 :(得分:2)
这似乎是 material-ui github 上的 well established issue。显然它源于使用布尔值进行联合歧视 - 我对 TS 还是个新手,所以只对这意味着什么有一个大致的了解!
我从这些线程中发现的最干净的方法是通过直接将 button
强制转换为 true到any
:
button
答案 1 :(得分:1)
这一切都归结为 intersection types 的工作原理。
基本上,您可以拥有一个或另一个:
因此,就我而言,因为我使用“li”作为具有 ListItemProps
泛型类型的类型参数,所以我不能只传递 button
道具。它必须被省略(或者,设置为 false):
interface MyItemProps {
name: string;
value: string;
}
function Item({ name, value, button /* omit the prop, don't pass it down to ListItem */, ...props }: ListItemProps<'li', MyItemProps>): ReactElement {
return (
<ListItem {...props} className="item">
<ListItemText primary={name} secondary={value || '-'} />
</ListItem>
);
}