原始组件有一些props。对于每个props,您可能想要
- 原封不动地穿过它
- 以某种方式修改
- 省略它
- 改变它的类型
您可能还想添加一些自己的新props。举个简单的例子,你只想添加一些新的props。我正在制作一种名为 的新型按钮MultiClick,它添加了一个可选的props:
type MultiClickProps = {
clickCount?: number;
} & JSX.IntrinsicElements["button"];
const MultiClick: React.FC<MultiClickProps> = ({
clickCount = 2,
...buttonProps
}) => {
// do some stuff
return (
<button {...buttonProps} />
);
};
当然,这不是很有用:如果最终结果是返回一个按钮,所有props都未经修改,那么“某些东西”如何做任何有意义的事情?
所以你可能想拦截和修改一些props:
const MultiClick: React.FC<MultiClickProps> = ({
clickCount = 2,
onClick,
...buttonProps
}) => {
const handleClick = (
event: React.MouseEvent<HTMLButtonElement, MouseEvent>
) => {
// do some stuff
onClick(event);
};
return (
<button {...buttonProps} onClick={handleClick}/>
);
};
这样,就有机会与包装组件的操作进行实际交互。
现在假设您不喜欢 onClick 的“事件”参数,并且想要替换其他东西,一个数字。要更改类型,您实际上必须省略旧的 prop 并重新编写它,如下所示:
type MultiClickProps = {
clickCount?: number;
onClick: (n: number) => void;
} & Omit<JSX.IntrinsicElements["button"], 'onClick'>;
您可以在此处查看完成的代码。
顺便说一下,这一切都取决于 JSX.IntrinsicElements 的存在,React 的人很友好地提供了它。假设您正在尝试从某个库中包装一个功能组件,该组件没有导出整洁的 props 类型?
幸运的是,您可以为任何用 Typescript 编写的功能组件生成自己的 props 类型,如下所示:
type PropsOf<T> =
T extends React.FunctionComponent<infer U> ? U : never;
如果应用于上面的函数,就像这样:
type MultiClickProps = PropsOf<typeof MultiClick>;
将评估为类似
type MultiClickProps = {
clickCount?: number;
} & React.ClassAttributes<HTMLButtonElement> & React.ButtonHTMLAttributes<HTMLButtonElement>