TypeScript Academy · Lección

Comprobación de exhaustividad con never

Detecte casos sin gestionar en tiempo de compilación con never.

Lección 3 de 413 pasos

Comprobación de exhaustividad con never es una lección gratuita de TypeScript Academy en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de TypeScript Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de TypeScript Academy incluye 4 lecciones en total.

El problema de la exhaustividad

Al añadir un miembro nuevo a una unión, es fácil olvidar gestionarlo en algún lugar. La comprobación de exhaustividad convierte ese descuido en un error de compilación.

type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "square"; side: number };

// If we add "triangle" later, we want every switch to complain.

El tipo never

El tipo never representa valores que nunca pueden producirse. Si se gestionan todos los casos, el valor que llega a la rama predeterminada tiene el tipo never.

function fail(): never {
  throw new Error("unreachable");
}
// never is assignable to nothing except never itself.

Asignar a never en el caso predeterminado

En la rama default, asigne el valor a una variable de tipo never. Si se gestionan todas las variantes, la asignación se compila; si no, produce un error.

type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "square"; side: number };

function area(s: Shape): number {
  switch (s.kind) {
    case "circle": return Math.PI * s.radius ** 2;
    case "square": return s.side ** 2;
    default:
      const _exhaustive: never = s;
      return _exhaustive;
  }
}
console.log(area({ kind: "square", side: 3 }));

Qué ocurre al olvidar un caso

Si añade un miembro triangle pero olvida su caso, s en la rama predeterminada ya no es never, por lo que la asignación falla durante la compilación.

// type Shape = ... | { kind: "triangle"; base: number; height: number };
// Now in default, s is { kind: "triangle"; ... }
// const _exhaustive: never = s; // Error: triangle not assignable to never

El helper assertNever

Una función assertNever reutilizable centraliza este patrón. Acepta never y lanza una excepción, dejando constancia de que la rama no debería poder alcanzarse.

function assertNever(value: never): never {
  throw new Error("Unhandled case: " + JSON.stringify(value));
}
console.log(typeof assertNever);

Usar assertNever en un switch

Llame a assertNever(s) en el caso predeterminado. Esto impone la exhaustividad durante la compilación y proporciona un error claro en tiempo de ejecución si se alcanza esa rama.

function assertNever(value: never): never {
  throw new Error("Unhandled: " + JSON.stringify(value));
}
type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "square"; side: number };

function area(s: Shape): number {
  switch (s.kind) {
    case "circle": return Math.PI * s.radius ** 2;
    case "square": return s.side ** 2;
    default: return assertNever(s);
  }
}
console.log(area({ kind: "circle", radius: 1 }).toFixed(2));

Seguridad en tiempo de compilación frente a tiempo de ejecución

La comprobación con never detecta los casos que faltan antes de ejecutar el código, y el error lanzado le protege si algo supera la comprobación de tipos durante la ejecución.

function assertNever(x: never): never {
  throw new Error("Unhandled: " + String(x));
}
// Compile error if a case is missing; runtime throw as a backstop.
console.log("two layers of safety");

Exhaustividad sin un caso predeterminado

Si su función tiene un tipo de retorno explícito y un switch cubre todos los casos, TypeScript también puede señalar que falta un retorno, otra forma de comprobar la exhaustividad.

type Light = "red" | "yellow" | "green";
function next(l: Light): Light {
  switch (l) {
    case "red": return "green";
    case "yellow": return "red";
    case "green": return "yellow";
  }
  // No default needed; all cases return.
}
console.log(next("red"));

Exhaustividad con cadenas if/else

La misma idea funciona con if/else. Después de gestionar cada variante, el else final recibe un valor never.

function assertNever(x: never): never { throw new Error("bad"); }
type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "square"; side: number };

function name(s: Shape): string {
  if (s.kind === "circle") return "circle";
  else if (s.kind === "square") return "square";
  else return assertNever(s);
}
console.log(name({ kind: "square", side: 2 }));

Por qué never es la herramienta adecuada

Como ningún valor se puede asignar a never, cualquier variante restante hace que la asignación falle. Esto convierte a never en el detector perfecto de casos no gestionados.

// Only never is assignable to never.
let x: never;
// x = "hi"; // Error
// Any concrete leftover type fails the same way.
console.log("never catches gaps");

La exhaustividad como red de seguridad al refactorizar

Con assertNever en todos los lugares necesarios, añadir un miembro a la unión produce una lista ordenada de errores de compilación que señala exactamente cada lugar que debe actualizar.

function assertNever(x: never): never { throw new Error("unhandled"); }
type Status = "idle" | "busy";
function render(s: Status): string {
  switch (s) {
    case "idle": return "Idle";
    case "busy": return "Busy";
    default: return assertNever(s);
  }
}
console.log(render("idle"));

Comprobación rápida: exhaustividad

Compruebe su comprensión de la comprobación de exhaustividad.

Resumen: exhaustividad con never

Ha aprendido a asignar el valor predeterminado a never (o a pasarlo a assertNever) para que el compilador le obligue a gestionar todas las variantes. Así, los casos olvidados se convierten en errores de compilación.

function assertNever(x: never): never { throw new Error("unhandled"); }
type Shape = { kind: "circle"; radius: number } | { kind: "square"; side: number };
function f(s: Shape) {
  switch (s.kind) {
    case "circle": return s.radius;
    case "square": return s.side;
    default: return assertNever(s);
  }
}
console.log(f({ kind: "circle", radius: 5 }));
Gratis para empezar

Aprende TypeScript con un tutor de IA — gratis

Escribe y ejecuta código real en tu navegador, obtén ayuda instantánea de un tutor de IA disponible 24/7 y continúa donde lo dejaste en la web o en la aplicación.

Cursos
101
Lecciones
352

Preguntas frecuentes

¿La lección «Comprobación de exhaustividad con never» es gratis?

Sí — el texto completo de «Comprobación de exhaustividad con never» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de TypeScript Academy, actualiza a CoddyKit PRO. El curso de TypeScript Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Comprobación de exhaustividad con never»?

Detecte casos sin gestionar en tiempo de compilación con never. Practicas TypeScript Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar TypeScript Academy?

No se requiere experiencia previa. TypeScript Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.

¿Cuánto tiempo toma la lección «Comprobación de exhaustividad con never»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de TypeScript Academy?

Sí. Cada lección de TypeScript Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Construcción de uniones discriminadas
  2. Restricción mediante el discriminante
  3. Comprobación de exhaustividad con never
  4. Modelado de máquinas de estados
← Volver a TypeScript Academy