TypeScriptで if (typeof value === "string") のように型を絞り込んだのに、その値を別の関数に渡した瞬間にまた赤線(型エラー)が出てくることがあります。「さっき確認したはずなのに、なぜまた怒られるのか」と戸惑う場面です。(AIが出したエラーを any で握りつぶさずに直す話ではなく、絞り込みそのものが関数の境界を越えると消えてしまう、という別の現象の話です。)

その場では絞り込みが効いている

まずは、絞り込みが正しく効いているケースです。

function printLength(value: string | number) {
  if (typeof value === "string") {
    // ここでは value は string 型として扱われる(赤線なし)
    console.log(value.length);
  }
}

if の中で typeof value === "string" と書いた瞬間から、その if ブロックの中では TypeScript が「ここは string のはず」と判断してくれます。これを型の絞り込み(narrowing)と呼びます。

別の関数に切り出すと、絞り込みが消える

同じ処理を、判定部分だけ別の関数に切り出すと状況が変わります。

function isString(value: unknown) {
  return typeof value === "string";
}

function printLength(value: string | number) {
  if (isString(value)) {
    // 赤線が出る: value はまだ string | number のまま
    console.log(value.length);
  }
}

isString 関数は truefalse を返しているだけなので、TypeScript から見ると「呼び出した結果が true だった」という情報しか残りません。isString の中でどんな判定をしていたかまでは追いかけてくれないため、printLength 側の value は絞り込まれないままになります。

対処: 型ガード関数にする

この場合の対処は、isString の戻り値の型を is を使った型ガードとして宣言することです。

function isString(value: unknown): value is string {
  return typeof value === "string";
}

function printLength(value: string | number) {
  if (isString(value)) {
    // 赤線が消える: isString の中身を信頼して value を string として扱う
    console.log(value.length);
  }
}

value is string という戻り値の型を書くことで、「この関数が true を返したら、引数は string 型だと約束します」と TypeScript に伝えられます。これによって、呼び出し側でも絞り込みが引き継がれるようになります。

instanceof や in 演算子でも同じことが起きる

typeof だけでなく、instanceofin 演算子を使った判定でも同じ現象が起きます。

class ApiError extends Error {}

function isApiError(err: unknown): err is ApiError {
  return err instanceof ApiError;
}
type Dog = { bark: () => void };
type Cat = { meow: () => void };

function hasBark(pet: Dog | Cat): pet is Dog {
  return "bark" in pet;
}

こちらも pet is Dog を書かなければ、hasBark を呼び出しただけでは絞り込みが引き継がれません。判定ロジックを関数として切り出すたびに、この「絞り込みが消える」現象に出会う可能性があります。

AIに実装を頼むときのポイント

AIに「この判定を関数に切り出して」とだけ頼むと、is を付けない普通の関数として実装されることがあります。動作確認では気づきにくく、後で別の場所から呼び出したときに初めて赤線に気づく、ということが起こりがちです。

依頼する際に「切り出した後も型の絞り込みが引き継がれるようにしてほしい」と一言添えておくと、型ガード(is を使った戻り値の型)を最初から提案してもらいやすくなります。エラーが出た時に「型ガードが必要な場面かもしれない」と見当をつけられるようになると、AIが返したコードの意図を自分で判断しやすくなります。


面談なしで、今日から始められます

この講座は 未経験から Next.js + Supabase + Claude Code で Webアプリを公開するまで を全24セッションで体系化した教材付きプランです。無料相談を挟まず、申し込んだその日から教材で学習を始められます。AIが学習パートナーになって何度でも質問でき、つまずいた所だけチャットで直接サポートします。

  • 今日から始める(教材完全版+月5,500円・チャット質問し放題・いつでも解約OK)→ https://menta.work/plan/20251?ref=menta-knowledge
  • いきなりは不安な方へ:無料の教材体験版もあります(最初の数セッション分)→ プラン詳細をご覧ください