在建立共用元件時,有時候會需要繼承到 HTML 元素的 props,這時候就需要針對原本的 props 做修改或擴充。但一個元件有這麼多 props,不可能一個一個來寫,這時候就可以用到 ComponentProps
來取得。
以下是範例,以 Button 元件為例:
import { ComponentProps } from "react";
type ButtonProps = ComponentProps<"button"> & {
icon?: React.ReactNode;
text: string;
};
export default function Button({ icon, text, ...props }: ButtonProps) {
return (
<button
className="flex items-center space-x-2 px-4 py-2 bg-blue-500 text-white rounded-md"
{...props}
>
{icon && <span>{icon}</span>}
<span>{text}</span>
</button>
);
}
這邊透過 ComponentProps
來取得 button 元素的所有 props 並加以擴充,增加自訂的 icon
和 text
屬性。
如果想要更明確的知道 props 是否包含 ref,也可以改用 ComponentPropsWithRef
或 ComponentPropsWithoutRef
。
在 React 開發時常會使用到第三方套件,大部分都有 @types/
套件來提供型別。但有時候並不是所有套件都會有提供,或是提供的型別文件不清楚。如果使用的元件沒有型別的話,也可以用 ComponentProps
來取得。
import { ComponentProps } from "react";
import { Button } from "some-external-library";
type MyButtonProps = ComponentProps<typeof Button>;
這樣我們就可以在自己的 Button 元件中擴展第三方元件的 props。
在使用 TypeScript 開發時,另一個常見需求是取得事件的型別。但通常事件型別名稱很長,難以記住。
有幾種簡單的方法可以取得這些事件型別:
將滑鼠懸停在事件的名稱上,TypeScript 會自動顯示該事件的型別。以下是 hover 到 onClick 事件後所顯示的結果:
雖然這是個快速方法,但複製起來貼上還是有點麻煩。
import { ComponentProps } from "react";
const handleClick: ComponentProps<"button">["onClick"] = (e) => {
//...
};
簡單又好記。
另外現在 AI 工具也很聰明,也會自動建議相關型別 (當然還是要檢查一下)。
參考資料:
https://www.totaltypescript.com/concepts/react-componentprops-type-helper
https://www.totaltypescript.com/react-component-props-type-helper
https://twitter.com/sebastienlorber/status/1512420374201446405