propsをジェネリックにしたい理由を考える、typeとinterface
propsをジェネリックにしたい理由
2/7にpropsの型をジェネリックにしたい旨を書いたんだけど、そもそもpropsの型をジェネリックにするユースケースってなにがある?というのを考えたい。
↑で書いたときは「Selectフィールドのコンポーネント」にジェネリックで型を渡せば、選択肢の一覧の型を柔軟に決められると思って書いた。
が、実際選択肢として表示に必要なプロパティはSelectコンポーネント側で定義することが多いという意見をもらって、「たしかに」となった。
idとnameとlabelみたいなプロパティを使って選択肢の一覧を構成することが多く(というかほとんど?)、これらの型はSelectコンポーネント側で定義しておき、使う側がこの型に合わせてpropsを渡せばいいのでは、という話で、ごもっとだと思った。
なので別にpropsでジェネリックな型を定義できなくても困らないケースかなと思ったのだけど、じゃあpropsをジェネリックにしたいのってどんなとき?というのを考えている。
詳しくないので「こういうのがあるよ!」というのを知っている人が居たら教えてほしい。
typeとinterface
interfaceとtypeの違い、そして何を使うべきかについて
なんか昔にどっちを使ったほうがいいかを学んだ気がするんだけど完全に頭から抜けたので読んだ。
interfaceもtypeもObjectの型を定義するが、interfaceはObjectの型に名前をつける、typeは作られた型に参照やtype aliasをつけるというニュアンス。
interfaceは同名の型を定義するとプロパティがマージされ、同じプロパティがある場合は痕から定義したもので上書きされる。
interface User {
id: stirng
name: string
}
interface User {
age: number
}
// => Userは
// {
// id: string
// name: string
// age: number
// }
// になる
typeは、そもそもObject以外の型も定義できる。
type Key = "Enter" | "Space" | "Escape"
const key: Key = "Delete" // => エラー
typeは型の上書きができず、同名の型をtypeで定義しようとするとエラーになる。
typeで型を拡張したいときはIntersection Typesを使えばできる。
type MacKey = Key & "Command"
interfaceはextends
を使うことで同様のことができる。
どちらを使うか
この記事を見て完全に納得したんだけど、interfaceを使うと知らないところで勝手に拡張されていて影響を受ける可能性があるがtypeはない、のでtypeを使うというのがとても理に適っているなと思った。
昔はinterfaceでしかできないことも多かったみたいだが今ではtypeもinterfaceとほぼ同様なことができ、拡張する場合は別名を作りUnion TypesやIntersection Typesを使うことでより分かりやすい拡張ができるtypeに統一してしまうのがいいなと思った。
基本的にtypeだけ使います。