TypeScriptのライブラリの型を拡張して、独自のpropsを渡せるコンポーネントを作る

2022-04-03

2022-04-03

3 min read

TypeScriptChakra UI

背景

先日TypeScriptのライブラリの型を拡張して、独自のpropsを渡せるようにしたコンポーネントを作ろうとしたら、エラーが出て少しハマりました。

ライブラリで提供されているコンポーネントを少し拡張して、システム内で利用したい場合はよくあると思います。

今回は例としてTypeScriptChakra UIというCSS フレームワークの型に、独自propsを渡せるように拡張してみます。

ちなみにライブラリが提供する関数やコンポーネントは一度ラップして使用することで、ライブラリ事態に致命的な変更が起きた場合、修正を行いやすくなるという記事を以前どこかで見ました。今回は詳しく触れませんが、コンポーネントを拡張しない場合でも、独自コンポーネントとして定義したものを使用した方が管理しやすいかもしれませんね。

課題

まず独自のpropsを普通に渡して、コンポーネントを拡張してみます。

Chakra UIのBoxPropsを用いて、Boxコンポーネントに独自のpropsを渡せるようにしたTitleBoxという独自コンポーネントを作ってみます。

function App() {
  return (
    <TitleBox
      title='タイトル'
      hoverBgColor='red.100'
      bg='blue.100'
    />
  );
}
type Props = BoxProps & {
  title: string;
  hoverBgColor: string;
}
const TitleBox:React.VFC<Props> = (props)=>{
  const {title, hoverBgColor} = props;
  return(
    <Box
      {...props}
      _hover={{
        background: hoverBgColor
      }}
    >{title}</Box>
  )
}

TitleBoxコンポーネントのtitlehoverBgColorが独自のpropsになります。

このように独自のpropsを渡そうとした場合、下記のようなエラーが出ます。

Warning: React does not recognize the hogeHoge prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase hogehoge instead. If you accidentally passed it from a parent component, remove it from the DOM element.

どうやら元々のDOM要素に無いプロパティ(独自のprops)を渡そうとしているため、エラーが出てしまっているようです。

解決方法

下記のように、分割代入で独自に渡しているpropsを取り出し、残りをスプレット構文(...basePropsの部分)でまとめます。これで、basePropsには本来のBoxPropsのデータのみになります。これをBoxコンポーネントに渡せばエラーを解決できます。

type Props = BoxProps & {
  title: string;
  hoverBgColor: string;
}
const TitleBox:React.VFC<Props> = (props)=>{
  const {title, hoverBgColor, ...baseProps} = props;
  return(
    <Box
      {...baseProps}
      _hover={{
        background: hoverBgColor
      }}
    >{title}</Box>
  )
}