gpt4 book ai didi

reactjs - 当组件是通用的(多态 react 组件)时键入点击处理程序

转载 作者:行者123 更新时间:2023-12-05 05:57:45 25 4
gpt4 key购买 nike

这是我的组件

interface Props<C extends React.ElementType> {
as?: C;
children: React.ReactNode;
size?: "mini" | "small" | "medium" | "large";
onClick?: (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
}

type ButtonProps<C extends React.ElementType> = Props<C> &
Omit<React.ComponentPropsWithRef<C>, keyof Props<C>>;

export const Button = <C extends React.ElementType = "button">({
children,
as,
size = "medium",
onClick,
...restProps
}: ButtonProps<C>) => {
const Component = as || "button";

return (
<Component {...restProps} className={`button-${size}`} onClick={onClick}>
{children}
</Component>
);
};

我可以像这样使用组件:

<Button as="a" onClick={(e) => console.log(e)}>Anchor button</a>

问题是点击处理程序的类型表明事件的类型是 React.MouseEvent<HTMLButtonElement, MouseEvent> ,但事实并非如此。应该是HTMLAnchorElement在这种情况下。

如何提供正确的类型?理想情况下我会以某种方式使用 C得到正确的 HTMLXyzElement

这是一个 TypeScript Playground link如果你愿意,你可以在那里玩代码

最佳答案

import React, { useRef } from "react";

type InferElement<T> =
T extends keyof JSX.IntrinsicElements
? JSX.IntrinsicElements[T] extends React.DetailedHTMLProps<React.AnchorHTMLAttributes<any>, infer Elem>
? Elem
: never
: HTMLElement

type Result = InferElement<'a'> // HTMLAnchorElement

interface Props<C extends React.ElementType> {
as?: C;
children: React.ReactNode;
size?: "mini" | "small" | "medium" | "large";
onClick?: (event: React.MouseEvent<InferElement<C>, MouseEvent>) => void;
}

type ButtonProps<C extends React.ElementType> = Props<C> &
Omit<React.ComponentPropsWithRef<C>, keyof Props<C>>;

export const Button = <C extends React.ElementType = "button">({
children,
as,
size = "medium",
onClick,
...restProps
}: ButtonProps<C>) => {
const Component: React.ElementType = as || "button";


return (
<Component {...restProps} className={`button-${size}`} onClick={onClick}>
{children}
</Component>
);
};

const Link = ({ to, children }: { to: string; children: React.ReactNode }) => {
return <a href={to}>{children}</a>;
};

export const ButtonUser = () => {
return (
<div>
<Button size="mini" disabled>
Button text
</Button>
<Button as="a" size="mini" href="test" onClick={(e) => console.log(e)}>
Button text
</Button>
<Button as={Link} to="/" size="mini">
Button text
</Button>
</div>
);
};

const jsx = <Button as="a" onClick={(e) => console.log(e)}>Anchor button</Button>

由于 JSX.IntrinsicElements 只是一个 html 元素的大 map ,您可以从 JSX.IntrinsicElements 推断 html 元素名称并将其用于回调参数。参见 InferElement util

关于reactjs - 当组件是通用的(多态 react 组件)时键入点击处理程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68727850/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com