こんにちは!りょた(@Ryo54388667)といいます(^o^)
コンポーネントに型引数を渡せるようにする方法について書いていきます。
- TypeScriptのいろいろな書き方を知りたい。
- 汎用的なコンポーネントを作成している人。
こんな人に読んでいただけると幸いです!
きっかけ
先日、another worksさんのLT会で見かけたことがきっかけです!
LT会で発表されている人の中で、下のようなコンポーネントの書き方を見かけました。
<Component<string> {…props} />
コンポーネントに型を渡している!?!?
個人的には初めて見た書き方でした!
けっこう、テンション上がりましたね〜
これができれば、Elementレイヤーのコンポーネント群の汎用性がグッと高まる気がしました。
自分のTwitterに投稿したところ、割とインプレッションあったので、界隈からみても、より良いコードだったのではないかと予想しています。
<Component<T> />
これ、おもしろそう!
コンポーネントにジェネリクス指定するのは初めて見ました!汎用性増しますね!— りょた.tsx@frontend (@Ryo54388667) January 25, 2023
ということもあり、深堀りしたいと思い、この記事を書く運びになりました!
コンポーネントに引数として型を渡せるようにするコード
こんな感じですかね。
//MyComponent.tsx
import { FC } from "react";
type Props<T> = {
data: T
}
const MyComponent = <T extends string>({data}: Props<T>) => {
return <div>{data}</div>
}
// 利用する箇所
<MyComponent<string> data="Data" />
type Props<T> = {
data: T
}
この部分で、
渡された引数の型をdataの型にしています。
続いて、
const MyComponent = <T extends string>({data}: Props<T>) => {
return <div>{data}</div>
}
ここで、通常の関数と同様に型引数を渡せるように書きます。
extendsを利用しない方法だと、
<T>({data}: Props)と書くとコンパイルエラーが出るので、
<T,>({data}: Props<T>)
カンマ(,)を書かないといけないようです。これは微妙な仕様ですね。。
ざっくりいうとこんな感じのコードです。
利用されるケース
実際、どのような場面で利用されるのか考えてみました。
ユーザーで振り分けるコンポーネント
例えば、有料会員とベーシック会員で表示するデータを柔軟に変更したい時に利用できるのかなと思っています。
<Component<PrimeUserType> data={data} />
<Component<BaseUserType> data={data} />
柔軟で、しかも型の恩恵も受けることができます。ただ、少しの違いであれば型のプロパティをオプショナル指定する方が手軽な気がします。。
undefindeをどのくらい許容するのか、チームの方針で採用するか決めるのが良さそうです!
Elementレイヤーの汎用的なコンポーネント
さまざまな型が渡されることが予想されるコンポーネントにも利用できると思いました。
<Button<UserData> data={data} />
<Button<ItemData> data={data} />
などなど。
使い方は多岐にわたります。
最後に
冒頭にも書きましたが、初めて見たのでとてもテンションが上がりました!
「これができるなら、あれもできるかも!」といろいろ想像する時が一番楽しいです。
これを利用して、型が理由で、コンポーネントの数を増やしていた箇所をリファクタリングしていきたいと思います。
僕自身、まだまだ未熟者なので、より良い書き方があれば、教えてください。
最後まで読んでいただき、ありがとうございます!
フロントまわりの技術記事も書いていますので、興味のある方はこちらも合わせて見てみください〜