ts-pattern
Para sustituir cadenas de if/else y switch por coincidencia de patrones tipada y exhaustiva.
Librería de pattern matching para TypeScript con inferencia de tipos y comprobación de exhaustividad.
Notas y contexto
Qué es
ts-pattern es una librería de pattern matching (coincidencia de patrones) para TypeScript y JavaScript, creada y mantenida por Gabriel Vergnaud. Toma una técnica habitual de la programación funcional y la lleva a TypeScript: en lugar de anidar if/else o encadenar switch, describes la forma de los datos como un patrón y obtienes una expresión declarativa, con narrowing de tipos en cada rama y comprobación de exhaustividad en tiempo de compilación. Es muy ligera (~2 kB), no tiene dependencias y se distribuye con licencia MIT.
Para qué sirve
- Sustituir condicionales anidados por una única expresión
match().with(...)legible y tipada. - Discriminar uniones de TypeScript (por ejemplo, estados
cargando | ok | error) con estrechamiento automático del tipo en cada rama. - Garantizar en compilación que has cubierto todos los casos con
.exhaustive(). - Hacer coincidir estructuras complejas: objetos, arrays, tuplas, sets, maps y primitivos.
- Extraer valores desde dentro de un patrón con
P.select()o validar formas conisMatching.
Cuándo usarlo
Encaja cuando tienes lógica basada en uniones discriminadas o en la forma de los datos y quieres que el compilador te avise si olvidas un caso. Es especialmente útil en reductores de estado, máquinas de estado, parsers o al renderizar según el estado de una petición. Si solo tienes dos o tres ramas simples, un switch nativo puede bastar; ts-pattern destaca cuando la exhaustividad y el narrowing aportan seguridad real.
Ejemplo
npm install ts-pattern
import { match, P } from 'ts-pattern';
type Resultado = { tipo: 'cargando' } | { tipo: 'ok'; datos: string[] } | { tipo: 'error'; mensaje: string };
const render = (r: Resultado): string =>
match(r)
.with({ tipo: 'cargando' }, () => 'Cargando...')
.with({ tipo: 'ok' }, ({ datos }) => `${datos.length} elementos`)
.with({ tipo: 'error' }, ({ mensaje }) => `Error: ${mensaje}`)
.exhaustive(); // error de compilación si falta cubrir un caso
Puntos clave
- Inferencia de tipos de primera clase: cada rama recibe el tipo ya estrechado (narrowed).
.exhaustive()convierte los casos no cubiertos en errores de compilación.- Patrones expresivos: comodines (
P._), por tipo (P.string,P.number), guardas con.when()y extracción conP.select(). isMatchingpermite usar los patrones como type guards fuera de unmatch.- Muy ligera (~2 kB), sin dependencias y con licencia MIT.
Ten en cuenta
- El máximo valor lo aporta en TypeScript: en JavaScript puro pierdes la comprobación de exhaustividad y el narrowing.
- Añade una dependencia y una pequeña curva de aprendizaje frente a un
switchnativo; para condicionales triviales puede ser innecesaria. - La documentación vive en el README del repositorio (no hay sitio de documentación aparte).