generated at
Polymorphic React Components
Componentの中のHTMLタグを多相にする
<Button as="a" /> とすれば <button> ではなく <a> になる感じ


要件
指定されたタグのみ選択できる
e.g. "a" | "button"
指定されたタグの標準のpropsのみ受け入れる
e.g. "a" を指定した場合は、 href= が使える
e.g. "button" を指定した場合は、 href= が使えない


ユースケース






そんなに頑張らなくても、これで十分な気がしてきた
ts
type AProps = { as: 'a'; href: string; }; type ButtonProps = { as: 'button'; onClick: () => void; }; type Props = AProps | ButtonProps; export const AddButton: React.FC<Props> = ({ as: Tag, ...props }) => { return ( <Tag className="bg-gray-400 hover:bg-gray-500 text-white font-bold py-2 px-4 rounded-full" {...props} > + </Tag> ); };








この記事、結論おかしくないかmrsekut
この定義だと、 <Button tagName="button" href="..."/> もvalidになってしまう
a button のpropsをUnionToIntersectionしているのがおかしい
要素の制限ができない
任意のタグを指定できてしまう
ts
export const ButtonDefaultAsType = 'button' as const export type ButtonDefaultAsType = typeof ButtonDefaultAsType export type ButtonOwnProps<E extends React.ElementType> = { children: React.ReactNode as?: E } export type ButtonProps<E extends React.ElementType> = ButtonOwnProps<E> & Omit<React.ComponentProps<E>, keyof ButtonOwnProps<E>> export const Button = <E extends React.ElementType = ButtonDefaultAsType>({ children, as, ...otherProps }: ButtonProps<E>) => { const Tag = as || ButtonDefaultAsType return <Tag {...otherProps}>{children}</Tag> }