type predicateでFirebaseのエラーハンドリングをする

前回type predicate使う場面が出てきてテンション上がって記事を書いた

あわせて読みたい
type predicateで配列のundefinedを取り除いた型を付ける 型が(T | undefined)[]になってる配列からundefinedを取り除いたT[]の配列を作成しようとした時のこと JS的には問題なかったけどTSで型の推論が(T | undefined)[]のまま...

その直後にもう一つtype predicate使う場面が出てきたのでメモ

TSのバージョンを4.4に上げた時にエラーになる部分が出てきたのでそれに対応するために使用した

目次

背景

TSを4.4にアップデートしたらエラー吐くようになった
内容見たらcatchの中のerrorオブジェクトが今までanyに推論されてたのがstrict: trueだとunknownに推論されるようになったらしい。

あわせて読みたい
Documentation - TypeScript 4.4 TypeScript 4.4 Release Notes

エラーハンドリングでerror.messageとかやってたのがerrorがunknownになったことで怒られるようになった

try {
  ...
} catch (error) {
  console.error(error.message) // エラー
  ...
}

narrowingによる対応

解決策としては下記のようにnarrowingしてやればok
errorはErrorオブジェクトであることを教えてあげればmessageプロパティが使える形になる

try {
  ...
} catch (error) {
  if (error instanceof Error) console.error(error.message)
  ...
}

基本これでokなんだけど、一箇所firebaseのエラーハンドリングの部分だけ困った

try {
  ...
} catch (error) {
    if (error.code === 'auth/account-exists-with-different-credential') {
      // エラーハンドリング
    }
}

元々これはfirebaseのドキュメントにも書いてある書き方なんだけど、Errorオブジェクトにはcodeプロパティがないので、他の部分と同じようにinstanceof Errorとするだけじゃだめだった

type predicateを使う

narrowingでerrorオブジェクトがcodeというプロパティを持つことを示したい
そんな時に使えるのがぼくらのtype predicate

以下のようにすると行けた

type FirebaseError = {
  code: string
  message: string
  name: string
}

const isFirebaseError = (e: Error): e is FirebaseError => {
  return 'code' in e && 'message' in e
}

try {
  ...
} catch (error) {
    if (
      error instanceof Error &&
      isFirebaseError(error) &&
      error.code === 'auth/account-exists-with-different-credential'
    ) {
      // エラーハンドリング
    }
}

Firebaseから型がexportされてるか分からなかったので、codeを持つ型を自分で定義してtype predicateしてやればerrorがFirebaseErrorに推論されるのでerror.codeが通るようになった

type predicateの使い方完全に理解した!!

まとめ

TSおもしれー!!!(2回目)

参考

あわせて読みたい
Documentation - TypeScript 4.4 TypeScript 4.4 Release Notes
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次