できない.dev

TypeScript で catch の「Object is of type 'unknown'」が解決できない

TypeScript 4.4 以降は useUnknownInCatchVariables(strict で既定有効)により catch の変数が unknown 型になる。
現行版は TS18046「'e' is of type 'unknown'」、旧版は TS2571「Object is of type 'unknown'」として出る。
instanceof や型ガードで絞ってからアクセスする。

#typescript#catch#unknown#error-handling#strict#TS18046#TS2571

公開: 更新:

要約

Object is of type 'unknown'.catch ブロックで出るのは、TypeScript 4.4 以降の useUnknownInCatchVariablesstrict: true で既定有効)により、catch (e)eany ではなく unknown 型になったため。unknown はそのままでは何もできないので、型を絞ってから 使う。
これは安全側に倒した正しい挙動で、握り潰さず対処する。

エラー文言はバージョンで変わる: 同じ原因でも、現行の TypeScript(5.x 系など)で catch 変数を絞らずに使うと error TS18046: 'e' is of type 'unknown'.e は変数名)が出る。
それ以前のバージョンや「unknown 値へのプロパティアクセス全般」では error TS2571: Object is of type 'unknown'. と表示される。どちらも unknown を絞っていないことが原因で、対処は同じ
この記事下部の「## 実行例」は TypeScript 5.9 での実測のため TS18046 を記録している。

よくある原因

  1. strict 既定: strict: true に連動して useUnknownInCatchVariables が有効になっている
  2. 未ナローイングのアクセス: catch (e) { console.log(e.message) } と直接プロパティを読んでいる
  3. reject 値の前提: Promise の reject や throw される値を any 前提のコードで扱っている
  4. 旧コードの移行: 4.4 より前に書かれた古い例外処理コードをそのまま移している

解決策

1. instanceof で絞る

try {
  doWork();
} catch (e) {
  if (e instanceof Error) {
    console.error(e.message);
  } else {
    console.error(String(e));
  }
}

Error 以外が throw される可能性も String(e) で受ければ漏れない。

2. 型ガード関数で検証する

function hasMessage(e: unknown): e is { message: string } {
  return typeof e === "object" && e !== null && "message" in e;
}
 
try {
  doWork();
} catch (e) {
  if (hasMessage(e)) console.error(e.message);
}

e is { message: string } の述語型で、必要な形だけを安全に取り出す。

3. any の多用を避ける

個別に catch (e: any) と書くこともできるが、型安全をその場で捨てることになる。
例外処理こそ未知の値が来る場所なので、unknown を絞る方針を基本にする。
詳しい背景は TypeScript 4.4 リリースノート を参照。

4. 移行期だけ設定で戻す

{
  "compilerOptions": {
    "useUnknownInCatchVariables": false
  }
}

大量の旧 catch を一度に直せないときの一時退避。
各オプションの意味は tsconfig の useUnknownInCatchVariables にある。
最終的には unknown を絞る形へ寄せる。

実行例

実際に上記の手順を node:20 環境で動かすと、useUnknownInCatchVariables が有効な状態の src/bad.tsTS18046: 'e' is of type 'unknown'. が発生し(終了コード 2)、instanceof Error による絞り込みおよび型ガード関数による絞り込みのいずれもコンパイルエラーなし(終了コード 0)で通過することが確認できる。

== versions ==
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
v20.20.2
Python 3.11.2
git version 2.39.5
 
                                                                               
                This is not the tsc command you are looking for                
                                                                               
 
To get access to the TypeScript compiler, tsc, from the command line either:
 
- Use npm install typescript to first add TypeScript to your project before using npx
- Use yarn to avoid accidentally running code from un-installed packages
v10.4.1
== run ==
--- TypeScript を install ---
Version 5.9.3
--- npx tsc (Object is of type unknown を想定)---
src/bad.ts(8,17): error TS18046: 'e' is of type 'unknown'.
tsc 終了コード: 2
--- 解消1: e instanceof Error で絞る ---
tsc 終了コード: 0
--- 解消2: 型ガード関数で property の有無を検証 ---
tsc 終了コード: 0

— 2026-06-07 時点の出力

この記事は役立ちましたか?