🦺

【TypeScript】ユーザー定義型ガード ~戻り値だけでなく型情報も返す関数~

2023/04/25に公開

要約

typeofやinstanceofによる型ガードを、インラインで書かなくても済むように関数化したい時
→型ガードの関数の戻り値でis演算子を使おう (ユーザー定義型ガード)

問題点

typeofやinstanceofによる型ガードを、インラインで書かなくても済むように関数化する。
ここでは例として、stringかどうか判定するisString関数の実装をしてみる。

function isString(a: unknown): boolean {
  return typeof a === 'string'
}

できた(?)
しかし上の関数を使ってみると型情報まで絞り込むことができないので、以下のようなエラーが出てしまう。

型情報は返さない
function example(input: string | number) {
  // ...
  if (isString(input)) {                 // inputの型情報までは返さない
    let formattedInput = input.toUpperCase() // inputの型が分からないのでエラーになる
  }
}

解決策

ユーザー定義の型ガード関数を定義するときは戻り値でis演算子を使う

function isString(a: unknown): a is string {
  return typeof a === 'string'
}

この関数の戻り値は booleanではなく、a is stringになっている。
これにより、isString関数がtrueを返す場合、その引数aはstring型であることがTypeScriptによって保証される。

function parseInput(input: string | number) {
  //...
  if (isString(input)) {                     // inputの型もstringと受け取る
    let formattedInput = input.toUpperCase() // stringの組み込み関数を使える(エラーにならない)
  }
}

ユーザー定義型ガードは1つのパラメータに限られるが、stringのような単純な型に限らず、ユーザーの定義した型でも利用できる。

https://zenn.dev/ubie_dev/articles/ts-infer-type-predicates#typescript-5.5から関数本体の実装から型を推論してくれるようになった

Discussion