never
Type for Exhaustive Type Checking in TypeScript
Context
- When handling union types in React apps (e.g.,
"loading" | "success" | "error"
), developers often forget to cover every case. - Without TypeScript, this can silently break your UI at runtime. With TypeScript’s never, you get compile-time safety that forces you to be exhaustive.
🚨 Without TypeScript – The Problem
// React without TypeScript
import React from "react";
function StatusMessage({ status }) {
switch (status) {
case "loading":
return <p>Loading...</p>;
case "success":
return <p>Data loaded successfully!</p>;
// ❌ Forgot to handle "error"
default:
// Will silently run for unexpected values
return <p>Unknown state</p>;
}
}
// At runtime, this could happen:
<StatusMessage status="error" />;
// UI shows "Unknown state" instead of an error message
👉 Issue
You don’t get any warning if "error" is unhandled. The bug only appears when the app runs.
✅ With TypeScript + never – Compile-Time Safety
// React with TypeScript
import React from "react";
type Status = "loading" | "success" | "error";
function StatusMessage({ status }: { status: Status }) {
switch (status) {
case "loading":
return <p>Loading...</p>;
case "success":
return <p>Data loaded successfully!</p>;
case "error":
return <p>Something went wrong.</p>;
default: {
// Exhaustive check using never
const _exhaustive: never = status;
return _exhaustive;
}
}
}
🔒 Why this is safe:
- If you add a new state (e.g., "idle") to Status but forget to handle it in the switch, TypeScript will throw a compile-time error at the never line.
- This guarantees you can’t accidentally miss a case.
🎯 Takeaway
- Without TS: Missed cases only show up at runtime → unstable apps.
- With TS + never: TypeScript enforces exhaustive handling at compile-time → safer apps and fewer bugs.
Top comments (0)