TypeScript | 基礎文法:配列・タプル – findの戻り値型

TypeScript
スポンサーリンク

findの基本的な動きと戻り値のイメージ

find は、配列の中から「条件を満たす最初の要素」を1つだけ返すメソッドです。
もし条件を満たす要素が1つも見つからなかった場合は、undefined を返します。

const array = [5, 12, 8, 130, 44];

const found = array.find(el => el > 10);
// found の中身: 12
// 型: number | undefined
TypeScript

ここで大事なのは、「見つかるかもしれないし、見つからないかもしれない」という性質が、そのまま戻り値の型に反映されていることです。
TypeScript はこの仕様を踏まえて、find の戻り値を常に「要素の型 | undefined」として扱います。


なぜ戻り値の型が「T | undefined」になるのか

JavaScriptの仕様がそのまま型に反映されている

JavaScriptの Array.prototype.find は、
「条件を満たす要素があればその値を返す。なければ undefined を返す」と定義されています。

TypeScriptはこの仕様を忠実に型に落とし込んでいるので、
配列の要素型が T のとき、find の戻り値は必ず T | undefined になります。

const nums = [1, 2, 3, 4]; // number[]

const result = nums.find(n => n > 2);
// 型: number | undefined
TypeScript

「絶対に見つかるはず」と人間が思っていても、
TypeScriptは「見つからない可能性もある」として扱います。
だからこそ、result にすぐプロパティアクセスしようとすると、
「Object is possibly ‘undefined’」というエラーが出るわけです。


findの戻り値をそのまま使うときに起きる典型的なエラー

「Object is possibly ‘undefined’」が出るパターン

type Item = { id: number; name: string };

const items: Item[] = [
  { id: 1, name: "Taro" },
  { id: 2, name: "Hanako" }
];

const found = items.find(item => item.id === 2);
// found: Item | undefined

// found.name; // エラー: Object is possibly 'undefined'
TypeScript

TypeScriptは「foundItem のときもあれば、undefined のときもある」と見ているので、
そのまま found.name にアクセスすると危険だと判断します。

ここで大事なのは、TypeScriptは「ロジック上は必ず見つかるはず」という前提を信用しないということです。
常に「見つからないケースもある」として扱うことで、安全側に倒しています。


undefinedをちゃんと扱うための基本パターン

if文でundefinedをチェックする

一番素直で安全なのは、「undefined かどうかを先に判定する」書き方です。

const found = items.find(item => item.id === 2);

if (found === undefined) {
  // 見つからなかった場合の処理を書く
} else {
  // ここでは found は Item 型として扱える
  console.log(found.name);
}
TypeScript

if (found === undefined) で分岐すると、
else の中では found の型が Item に絞り込まれます。
TypeScript的にも、人間的にも一番分かりやすいパターンです。

null合体演算子(??)で「見つからなかったときの代わり」を決める

「見つからなかったときは、代わりの値を使いたい」というケースなら、?? が使えます。

const result = nums.find(n => n > 10) ?? 0;
// result: number
TypeScript

findundefined を返した場合だけ、右側の 0 が使われます。
これで「戻り値から undefined を消して、純粋な number にする」ことができます。


「絶対に見つかる」と分かっているときの扱い方

非nullアサーション(!)で「ここは本当にある」と宣言する

「この配列と条件の組み合わせなら、ロジック上絶対に見つかる」と自分で保証できる場合、
! を使って「ここでは undefined じゃない」とコンパイラに宣言することもできます。

const found = items.find(item => item.id === 1)!;
// 型: Item

console.log(found.name);
TypeScript

ただし、これは完全に自己責任です。
もし実際には見つからなかった場合、実行時にエラーになります。
「本当に100%そう言い切れるか?」を自分に問い直してから使うべきテクニックです。


型述語(type predicate)とfindの組み合わせ

特定の型だけを見つけたい場合

filter と同じく、find にも「型を絞り込む関数(型述語)」を渡すことができます。

type Item = { id: number; name: string } | { id: number; deleted: true };

function isActive(item: Item): item is { id: number; name: string } {
  return "name" in item;
}

const items: Item[] = [
  { id: 1, name: "Taro" },
  { id: 2, deleted: true }
];

const found = items.find(isActive);
// 型: { id: number; name: string } | undefined
TypeScript

ここでも戻り値は ... | undefined のままですが、
「見つかったときの型」がちゃんと { id: number; name: string } に絞り込まれています。
あとはさっきと同じように、undefined をどう扱うかを決めればOKです。


初心者がまず掴んでおきたい「findの戻り値型」の感覚

find の戻り値型の本質は、たったひとつです。

「見つかるかもしれないし、見つからないかもしれない」 → T | undefined

だからこそ、

undefined を if でちゃんと分岐する
?? で「見つからないときの代わり」を決める
どうしてもなら ! で「ここは絶対ある」と宣言する

この3パターンのどれで扱うかを、その場その場で選ぶことになります。

「find は“必ず見つかる”とは限らない」
この前提を型レベルで強制してくれるおかげで、
「見つからなかったときのことを考え忘れていた」というバグを、コンパイル時にかなり潰せるようになります。

タイトルとURLをコピーしました