🤹‍♂️

Arrow関数と関数宣言のneverの返り値の挙動の違い

に公開

Playgroundで確認できる。

Arrow Functionの返り値がneverの場合

type Result = { ok: true; data: "awesome" } | { ok: false; error: Error };

const notWorking = (): never => {
    throw new Error("Something Error ... !");
}

const main = (result: Result) => {
    if (!result.ok) {
        notWorking();
    }
    result.ok;   // boolean;
    result.data; // 型エラーになる
}

Functionの返り値がneverの場合

type Result = { ok: true; data: "awesome" } | { ok: false; error: Error };

function returnNeverValue() : never {
  throw new Error("Something Error ... !");
}

const main = (result: Result) => {
    if (!result.ok) {
        returnNeverValue();
    }
    result.ok;   // false
    result.data; // 型エラーにならない
}

見つけた背景

Next.jsのredirect関数の実装を見ていたら、直感的にはどうもType Guard効いてないよなぁ、という実装を調査してみたら、摩訶不思議。ちゃんと型チェック効いていたので調査したら見つけた挙動。

https://nextjs.org/docs/app/api-reference/functions/redirect#server-component

参考文献

この挙動はTypeScript 3.7のときにneverの挙動改善で追加されたもの。functionがneverを返す場合はエラーがthrowされたか、processがexitされたかを意味する。

HELP

公式ドキュメントに、本文と同等の内容のドキュメントはどこにあるのだろうか...?
我々調査隊ははアマゾンの奥地へと向かった....

Discussion