「TypeScriptの型入門」で手を動かす - その14
本日は「TypeScriptの型入門」の「Conditional Types」から手を動かします。
Conditional Types
- TypeScript2.8で久々に登場したやばい型らしい
- どういう表現やねん
- 型レベルの条件分岐が可能な型
おすすめ記事
Conditional Typesとは
T extends U ? X : Yという構文で表現される- 4つの型を使う
- TがUの部分型ならX、そうでなければYになる
- 表現力がすざまじく、いろんな問題を解決できる
mapped typesの限界
- deepなマッピングできないという問題がある
- Readonly
では、プロパティは全てreadonlyにできるが、プロパティがオブジェクトだった場合に、そのオブジェクトのプロパティはreadonlyにならない
- Readonly
- deepなreadonlyの方が需要があった
- へー、そうなんだ。どういうユースケースだろうか
- 再帰的にDeepReadonly
を適用するtypeのサンプルコードを実行してみたが、特にエラーにならなかたった。。。 - TypeScriptが頭良くなったのかな。
conditionaly typeによる、DeepReadonly
- くそ難しい
- DeepReadonly
の本質は、conditional typeが遅延評価されるところにある - らしい
- conditional typeで評価時に無限に再帰することを防いでいる
- ???て感じ
まぁ、内容は70%くらいしか理解できなかったが、プレイグラウンドの方に色々 検証コードは書けたので、理解は深まった。とする。
conditional typeにおける型マッチング
- conditional typenのさらなる強力な機能
- conditional typeの条件部で新たな型変数を導入できる
infer R
- conditional typeの条件部で新たな型変数を導入できる
- 例:
type ReturnType<T> = T extends ( ...args: any[]) => Infer R ? R : T- T が関数の型のときは返り値は関数の返り値のR型
- Tが関数の型でないときは返り値は、T型
infer Rがポイント。conditional typeの条件分岐で型変数を定義できる(...args: any[]) => 何らかの型が型変数を使えない場合T extends [ 条件部 ] ? [trueの場合] : [falseの場合]- 条件部で
infer Rで型変数を定義して、分岐部分(trueの場合)で利用できる - falseの場合、ではRは使えない。そもそも条件部に合致してないのでRが存在しないかもだから
- 条件部で
inferを複数箇所に現れることも可能- 記事の例では、以下が興味深かった
- Uがconvariantな位置にある場合はユニオン型で表現される
- Vがcontravariantな位置にあるアバイはintersection型で表現される
- メソッド型の引数でinferを使う
conditional typesによる文字列操作
inferとテンプレートリテラル型を組み合わせることで、型レベルの文字列操作が可能に"Hello, world!"'型というリテラル型からworld`部分を抜き出すことができる
おわりに
終わったー、これも時間かかった。時間かかりすぎて忘れてるのもあるなw
そして、これで入門編という。
続編がでてるらしいので、それをやってみるかー