Una sentencia switch de TypeScript es el switch de JavaScript con comprobación de tipos. Compara un valor con cada case usando ===, ejecuta la rama que coincide y se detiene en break o return. TypeScript estrecha el valor evaluado dentro de cada case y puede comprobar que se maneja cada valor posible.
Las etiquetas apiladas (case "sat": case "sun":) comparten una rama. return termina la función, así que no hace falta break después.
Sintaxis
switch (expression) {
case value1:
// runs when expression === value1
break;
case value2:
case value3:
// runs for value2 or value3
break;
default:
// runs when nothing else matched
}
- La coincidencia usa igualdad estricta,
===:case 1no coincide con el string"1". - Sin
break,returnnithrow, la ejecución continúa en el siguiente case (fallthrough). defaultes opcional y puede ir en cualquier sitio, aunque lo habitual es ponerlo al final.- Un valor de
caseque TypeScript puede demostrar que nunca coincide es el error TS2678. Para un parámetro de tipo"a" | "b",case "c":daType '"c"' is not comparable to type '"a" | "b"'., lo que detecta erratas en las etiquetas.
Estrechamiento dentro de cada case
En cada case, TypeScript sabe qué valor coincidió y estrecha el tipo. Esto es lo más útil con una unión discriminada: haz switch sobre la propiedad etiqueta compartida, y cada case ve la variante correspondiente con sus propias propiedades.
shape.radius solo compila en el case "circle". Fuera de él, shape podría ser un rectángulo, que no tiene radius. No hay default, y aun así la función se comprueba como que devuelve number, porque TypeScript ve que los tres case cubren todos los kind. Hay más patrones basados en esto en la página de uniones discriminadas.
Switch exhaustivo con never
La función de arriba deja de compilar si se añade una cuarta forma sin su case (TS2366, falta un return). Eso solo funciona cuando la función devuelve un valor. Para una garantía que también funcione en código void y dé un mensaje más claro, añade un default que asigne el valor a never:
index.ts(14,19): error TS2322: Type '{ kind: "triangle"; base: number; height: number; }' is not assignable to type 'never'.
Tras los case manejados, el único tipo que le queda a shape es la variante del triángulo, y no se puede asignar a never. El error nombra exactamente lo que falta. Añade case "triangle": return (shape.base * shape.height) / 2; y el default ve never, así que el bloque compila e imprime 9. El throw sigue protegiendo contra datos erróneos en tiempo de ejecución, como un kind llegado desde JSON que los tipos no preveían.
Muchos proyectos envuelven la comprobación en una función auxiliar:
La misma técnica funciona con enums: haz switch sobre el valor del enum y pásalo a assertNever en el default.
switch (true) para rangos y condiciones
switch compara valores, así que los rangos necesitan un truco: haz switch sobre true y escribe una condición en cada case. Desde TypeScript 5.3, esas condiciones estrechan tipos igual que las sentencias if.
Los case se evalúan en orden, así que pon primero los más específicos. Si esto se lee mejor que if / else if es cuestión de gustos; el comportamiento es el mismo.
Fallthrough y break
Un case con código pero sin break, return ni throw cae en el siguiente case. Eso casi siempre es un bug. La opción del compilador noFallthroughCasesInSwitch (no forma parte de strict) lo convierte en el error TS7029, Fallthrough case in switch., pero sigue permitiendo etiquetas vacías apiladas.
Un fallthrough deliberado como este funciona, pero con noFallthroughCasesInSwitch activado hay que reescribirlo, por ejemplo con comprobaciones if separadas. Normalmente queda más claro de todos modos.
Variables dentro de los case
Todo el cuerpo del switch es un único bloque, así que una const declarada en un case es visible (y redeclararla es un error) en los demás. Envuelve un case entre llaves para darle su propio ámbito:
Sin las llaves, la segunda const unit es el error de compilación TS2451, Cannot redeclare block-scoped variable 'unit'.
switch frente a búsqueda en un objeto
Cuando cada case solo asigna un valor a otro valor, un objeto tipado con Record es más corto, y TypeScript comprueba que están todas las claves:
Omitir una clave es un error de compilación, lo que da la misma exhaustividad que una comprobación con never. Reserva switch para los case que ejecutan lógica distinta, estrechan variantes de una unión o retornan antes.
Preguntas frecuentes
¿Cómo se escribe una sentencia switch en TypeScript?
Exactamente igual que en JavaScript: switch (value) { case "a": ...; break; default: ... }. Los case se comparan con ===. TypeScript añade comprobaciones: un valor de case que nunca puede coincidir con el tipo evaluado es un error (TS2678), y dentro de cada case la variable evaluada queda estrechada a ese case.
¿Cómo hago exhaustivo un switch en TypeScript?
Añade un default que asigne el valor a una variable de tipo never: default: { const unreachable: never = value; throw new Error(...) }. Cuando se manejan todos los miembros de la unión, ahí el valor es never y compila. Cuando falta uno, el compilador informa del miembro que falta (TS2322).
¿Cómo manejo varios case con el mismo código en un switch de TypeScript?
Apila las etiquetas sin código entre ellas: case "sat": case "sun": return "weekend";. Los case vacíos caen en el siguiente. La opción noFallthroughCasesInSwitch solo marca los case que tienen código y no tienen break ni return, así que las etiquetas apiladas siguen permitidas.
¿switch (true) estrecha tipos en TypeScript?
Sí, desde TypeScript 5.3. En switch (true) { case typeof x === "string": ... }, x se estrecha a string dentro de ese case, igual que en un if. Es una alternativa legible a una cadena de if/else if con comprobaciones de rangos o de tipos.