参考にさせていただいたページ
とても参考になる入門と初級の記事です。
はじめに
以下のページを読んで、Mapped Typesが理解できる人はこの記事を読む必要は全くありません。
これらのページを読んでもMapped Typesを全く理解できないという人が、Mapped Typesを理解していく為のとっかかりをつかむ。
この記事は、そんな「超入門」記事になっています。
Mapped Typesを使うと、stringの部分型、numberの部分型、symbolの部分型、をキーとしたオブジェクトの型を定義することができます。
部分型についての前提知識
例えば 'foo' | 'bar'
のようなstring literal型は、string型の部分型です。
Mapped Typesの最も簡単な例
以下のようにMyObj型を定義した場合、
type MyObj = {[Key in 'foo' | 'bar']: number};
MyObj型は、以下のように定義したのと同じ型になります。
type MyObj = { foo: number; bar: number; }
'foo' | 'bar'
が順番に変数Keyに入り、MyObj型のキーになっていることがわかります。
'foo' | 'bar'の部分について
さきほどの「Mapped Typesの最も簡単な例」の in
の右側の 'foo' | 'bar'
の部分には、string | number | symbol
の部分型が使用できます。
今回の例でいうと、stringの部分型である 'foo' | 'bar'
を使用しています。
当然ですがbooleanなどは使用できません。
Genericsを使ってMyObj型を定義する
Genericsを使って、型を返す関数みたいなものが作れます。
以下のように書いても、MyObj型は「Mapped Typesの最も簡単な例」で定義したものと同じMyObj型になることがわかると思います。
// Genericsを使ってMyMappedType型を定義(型を返す関数みたいなものを定義) type MyMappedType<T extends string | number | symbol> = { [Key in T]: number } // MyMappedType<T>を実行して、MyObj型を定義 type MyObj = MyMappedType<'foo' | 'bar'>
さきほど説明したように、[Key in T]
のTにはstring | number | symbol
の部分型しか使用できないため、以下のようにMyMappedType型を定義する時点で型引数Tは string | number | symbol
の部分型であることを明示しています。
MyMappedType<T extends string | number | symbol>
MyMappedTypeの型引数Tとして、string literal型を渡すことが決まっているのであれば以下のようにstringの部分型であることを明示するのが良いと思います。
MyMappedType<T extends string>
FooBar型を定義する
以下のようにFooBar型を定義しても同じMyObj型が定義できることがわかると思います。
// FooBar型を定義 type FooBar = 'foo' | 'bar' // Genericsを使ってMyMappedType型を定義(型を返す関数みたいなものを定義) type MyMappedType<T extends string | number | symbol> = { [Key in T]: number } // MyMappedType<T>を実行して、MyObj型を定義 type MyObj = MyMappedType<FooBar>
おわりに
今回、以下のようにMyObj型のvalueの型はnumberで固定していますが、
{ [Key in T]: number }
以下のように変数Keyをオブジェクトのvalueとして使うこともできます。
{ [Key in T]: Key }
そうするとMyObj型は以下のようになります。
type MyObj = { foo: "foo"; bar: "bar"; }
超入門記事なのでここまでにしますが、以下の記事を読むと、より発展的な使い方やunion distributionなどについて学ぶことができます。
少しでも誰かの理解の助けになれば幸いです。