「TypeScriptの型入門」で手を動かす - その14

本日は「TypeScriptの型入門」の「Conditional Types」から手を動かします。

qiita.com

プレイグラウンドで手を動かす

Conditional Types

  • TypeScript2.8で久々に登場したやばい型らしい
    • どういう表現やねん
  • 型レベルの条件分岐が可能な型

おすすめ記事

qiita.com

Conditional Typesとは

  • T extends U ? X : Y という構文で表現される
    • 4つの型を使う
  • TがUの部分型ならX、そうでなければYになる
  • 表現力がすざまじく、いろんな問題を解決できる

mapped typesの限界

  • deepなマッピングできないという問題がある
    • Readonlyでは、プロパティは全てreadonlyにできるが、プロパティがオブジェクトだった場合に、そのオブジェクトのプロパティはreadonlyにならない
  • deepなreadonlyの方が需要があった
  • 再帰的にDeepReadonlyを適用するtypeのサンプルコードを実行してみたが、特にエラーにならなかたった。。。
    • TypeScriptが頭良くなったのかな。

conditionaly typeによる、DeepReadonly

まぁ、内容は70%くらいしか理解できなかったが、プレイグラウンドの方に色々 検証コードは書けたので、理解は深まった。とする。

conditional typeにおける型マッチング

  • conditional typenのさらなる強力な機能
    • conditional typeの条件部で新たな型変数を導入できる
      • infer R
  • 例: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

そして、これで入門編という。

続編がでてるらしいので、それをやってみるかー