IT-Q

const scores = ids.map((id) => scoreMap.get(id)).filter((s) => !!s) と書いたのに、scores が (number | undefined)[] のままで、合計を出すところでエラーになります。どうしますか。

filter((s) => !!s) は 0 も消すので、TypeScript は型を絞り込みません。s !== undefined と書けば、5.5 以降は型述語が推論されて number[] になります。0 が消える不具合も防げます。

面接官が見ているのはTypeScript が型を絞らない理由が、実際の不具合(0 を落とす)だと気づけるか。

よくある答えと、面談でどう見られるか

  • !!s だと 0 点も消えてしまう。.filter((s) => s !== undefined) に直す。5.5 以降なら、これで number[] に絞り込まれる
    その通りです。公式のリリースノートが、まさにこの例を「本物の不具合」として挙げています。
  • .filter((s): s is number => !!s) と型述語を書く
    型は通りますが、0 点が消える不具合は残ったままです。TypeScript は型述語の中身が正しいかを確かめません。
  • as number[] を付ける
    型は通りますが、0 点が消える不具合はそのままです。
  • TypeScript が filter を理解できない制限なので、! を付けて使う
    制限ではありません。0 を消してしまうので、TypeScript はわざと絞り込んでいません。

模範解答

undefined だけを外すように、.filter((s) => s !== undefined) と書きます。

!!s は、undefined だけでなく 0 も偽として外します。0 点の人がいれば、その人の点数が消え、平均が上振れします。

TypeScript 5.5 から、filter に渡した関数から型述語(s is number)が推論されるようになりました。ただし「true なら number、false なら number ではない」と言い切れるときだけです。!!s は false のときに 0(number)もありうるので、推論されません。公式のリリースノートは、まさにこの例を挙げて「本物の不具合」だと説明しています。

s !== undefined なら言い切れるので、scores は number[] になります。

対象: TypeScript 5.x〜7.0 照合した一次資料: 公式ドキュメント 照合: 2026-10-25 最終更新: 2026-10-25
お使いの版で挙動が違う場合があります。誤りに気づいたらこの解説を報告するから教えてください。

ここからどう深掘りされるか

この問いに答えられた場合、面談は次の質問に進みます。