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

本日は「TypeScriptの型入門」の「オブジェクト型再訪」と「asによるダウンキャスト」で手を動かします!

qiita.com

オブジェクト型再訪

  • プロパティに対して修飾子をつけられる
    • ?readonly

?

  • 省略可能を示す
  • ?がついたプロパティの型は指定した型 | undefinedとなる。
    • 任意プロパティで取得できないことがあるため

undefinedとのunion型のほうがおすすめらしい

  • ?をつけずに型 | undefinedと指定した場合はプロパティ自体は存在してないと行けない
    • ?よりこっちの方がおすすめらしい
    • ?はプロパティが無い場合に、本当に無いのか書き忘れなのかの区別ができない
    • 後者(undefinedとのunion型)は書き忘れを防ぐことができる
  • ?が必要なパターンとは?
    • 本当に無くても良いオブジェクトを渡すのは、関数にオプションオブジェクトを渡すときくらい
      • なるほど。

exactOptionalPropertyTypes

  • オプショナルなプロパティの挙動の定義
    • デフォルトは無効
    • TypeScript4.4で追加
  • 無効なとき
    • bar?: numberbar?: number | undefinedとナオジ
      • barにundefinedを明示的に入れることができる
  • オプションがONなら、undefinedはありえないので、プロパティが存在するか、値が入っているかの2択になる
    • in演算子を用いて絞り込みができる

readonly

  • 再代入できなくする
  • constのプロパティ版と考えてよい
  • 素のJavaScriptでもObjectプロパティ定義で、writable属性があるが、型システムに組み込むのは筋が悪いらしく、独自の方法を取っているらしい
  • ただし、readonlyではない型を経由して書き換えることができるので、過信してはいけない

インデックスシグネチャ

  • [key: string]: numberの部分。任意のstring型のプロパティ名に対して、number型を持つという定義
  • undefinedになるプロパティを参照しても、コンパイルエラーにならない。
    • 危険
  • インデックスシグネチャはオブジェクトを辞書の用に使うときに使える仕組み
    • でも、Mapがあるので、Mapを使った方がよい
interface MyObj {
  [key: string]: number
}

関数シグネチャ

  • オブジェクト型の記法で関数型を表現する方法がある
  • 以下の(arg: number):void部分
    • 本来はf : (arg:number) => void みていな関数型をプロパティに付与するのが普通だと思う。
  • ちょっと使い所はわからなかったが、関数にプロパティを付与した型を定義できる
interface Foo {
  (arg: number): void;
}
const f: Func = (arg: number) => { console.log(arg) }

newシグネチャ

  • コンスタントであることを表すシグネチャ
  • new():T の部分
interface Ctor<T> {
   new() : T
}

asによるダウンキャスト

  • 式 as 型と書く
  • ダウンキャストとは派生型の値を部分型として扱う
  • string | number型をnumber型として扱う
  • asを使っても全く関係ない2つの値を変換できない
    • string型の値をas numberでnumber型に代入なんてことはできない
      • できなかったんか。
    • any型かunknown型を経由すれば変換できる
  • asはアップキャストもできる
    • 部分型を派生型として扱うってことかな。
    • asを使わなくてもアップキャストはできるので、アップキャストでasを使うのはやめたほうがよい。
      • 危険なダウンキャストとの見分けがつかなくなるから
      • リテラル型をプリミティブ型に代入とかもアップキャストか
        • 1型をnumber型に代入

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

本日はここまで、次は「readonlyな配列とタプル」で手を動かします!