Extending TypographyProps and TextFieldProps



我正在用TypeScript和Material UI (MUI)制作一个React组件。

它是一个呈现输入或文本的组件。

你使用道具mode在它们之间切换,

如果你设置modeview,它将渲染文本。

如果你将modeprop设置为edit,它将渲染输入。

代码如下:

import { Typography, TextField } from '@mui/material'
import type { TypographyProps, TextFieldProps } from '@mui/material'
interface InputComponentProps {
mode: 'edit' | 'view'
content?: string
}
type EditModeProps = TextFieldProps & {
mode: 'edit'
} & InputComponentProps
interface ViewModeProps extends TypographyProps, InputComponentProps {
mode: 'view'
}
export default function InputComponent(props: EditModeProps | ViewModeProps) {
const { mode, content, ...compProps } = props
if (mode === 'edit') return <TextField value={content} {...(compProps as EditModeProps)} />
if (mode === 'view') return <Typography children={content} {...(compProps as ViewModeProps)} />
}

TypeScript没有抱怨。但是,现在当我使用这个组件时,我在外部遇到了问题。

我通常可以这样使用,没有问题:

<InputComponent mode="edit" />
<InputComponent mode="view" />

但是,我不能这样做:

import InputComponent from './InputComponent'
interface UserProfilePageProps {
mode: 'edit' | 'view'
}
export default function UserProfilePage(props: UserProfilePageProps) {
const { mode } = props
// the following works
/* return <InputComponent mode={'view'} content="hello world" /> */
/* return <InputComponent mode={'edit'} content="hello world" /> */
// the following works but its showing a compile time error?
return <InputComponent mode={mode} content="hello world" />
}

现在TypeScript说:

Type '{ mode: "edit" | "view"; }' is not assignable to type 'IntrinsicAttributes & (EditModeProps | ViewModeProps)'.
Type '{ mode: "edit" | "view"; }' is not assignable to type 'ViewModeProps'.
Types of property 'mode' are incompatible.
Type '"edit" | "view"' is not assignable to type '"view"'.
Type '"edit"' is not assignable to type '"view"'.

CodeSandbox

TypeScript试图将你传递给InputComponent的道具匹配到EditPropsViewProps,并且由于UserProfilePagePropsmode可以是editview,因此存在歧义。这就是联合类型的工作方式。

你必须通过显式设置mode="view"mode="edit"来告诉TypeScript这些道具属于联合的哪一部分。另一种方法可以是命令完全跳过匹配,即<InputComponent {...({ mode, content: 'hello world' } as Parameters<typeof InputComponent>[0])} />

相关内容

  • 没有找到相关文章

最新更新