type Props = { title: string; children: ReactNode | undefined; } const Heading = ( { title, children }:Props ) => { return ( <> <h1>{ title }</h1> <div>{ children }</div> </> ); }
こんな感じでコンポーネントを書いていたところ、PropsWithChildren
を使えばいいじゃん、と教えてもらうなどしました。で、ジェネリクスについて掘り下げて教えてもらったので備忘録。
type Props = PropsWithChildren<{ title: string }> // type Props = { title: string } & { children?: ReactNode | undefined } と同義 const Heading = ( { title, children }:Props ) => { return ( <> <h1>{ title }</h1> <div>{ children }</div> </> ); }
https://typescript-jp.gitbook.io/deep-dive/type-system/generics
https://js.studio-kingdom.com/typescript/handbook/generics
https://qiita.com/k-penguin-sato/items/9baa959e8919157afcd4
ジェネリクスは一言で言うと外から設定できる型定義のこと。
@types/react にはいろいろな便利な型が用意されてるので、自前で時間かけて書くよりもともとあるものを使ったほうが時短になってよい。(そういう型があるってのはコード見ないとわからないけども………)
PropsWithChildrenだけじゃなく、大体の関数にジェネリクスは定義されている。
おなじみ useStateもジェネリクスがあるので、こういうことができる。
// Todoリストの状態管理 const [state, setState] = useState<'ready' | 'inprogress' | 'completed' | ''>(''); // レビューの星管理 const [reviewStar, setReviewStar] = useState<1 | 2 | 3 | 4 | 5>(1);
useState
自体、特に型定義しなくても引数の中身を見て推察してくれるけど、中身を絞りたいときにはとても有用。
もしくは、初期値をnull
にした場合、null
しか受け付けてくれなくなるので、ジェネリクスに ReactNode
をいれるなど。
// これだと setName で nullしか入らなくなる const [name, setName] = useState(null); // ジェネリクスにReactNodeを入れておくと、型がReactNodeになるのでnull以外も設定できる const [name, setName] = useState<ReactNode>(null);
ジェネリクスは沼らしいので細かく設定しすぎたり時間かけ過ぎたりするのは本末転倒だから気をつける!