
TypeScript: Tipos avanzados, subtipos y varianza
- Dacadev
- Programación , Typescript
- 21 de junio de 2026
Tabla de Contenido
Note
Octavo artículo de la serie sobre TypeScript. Abordaremos la teoría que sustenta el sistema de tipos: subtipos, supertipos, la jerarquía completa, los tipos unknown y never, y la varianza.
Comprender la relación entre tipos es lo que separa a quien usa TypeScript de quien lo domina. El compilador decide qué asignaciones son válidas aplicando reglas de subtipado y varianza. Una vez interiorizadas estas reglas, los errores del typechecker dejan de ser obstáculos crípticos y se convierten en información precisa sobre el diseño de tus tipos.
Subtipos
La regla fundamental del subtipado se enuncia así:
Info
Si tienes un tipo A y un tipo B donde B es subtipo de A, entonces puedes usar B en cualquier lugar donde se espere un A.
Algunas relaciones de subtipo en TypeScript:
Arrayes subtipo deObject.Tuplees subtipo deArray.- Todo es subtipo de
any. neveres subtipo de todo.- Si una clase
BirdextiendeAnimal, entoncesBirdes subtipo deAnimal.
Aplicado a la práctica, esto significa que donde se necesite un Object puedes usar un Array; donde se necesite un Array puedes usar una Tuple; y donde se necesite un Animal puedes usar un Bird.
Supertipos
Un supertipo es la relación inversa:
Info
Si tienes un tipo A y un tipo B donde B es supertipo de A, entonces puedes usar A en cualquier lugar donde se espere un B.
Las relaciones de supertipo reflejan en espejo a las anteriores:
Arrayes supertipo deTuple.Objectes supertipo deArray.anyes supertipo de todo.Animales supertipo deBird.
La jerarquía de tipos
Todas estas relaciones forman una jerarquía con un tipo en la cúspide (top type) y otro en el fondo (bottom type):
flowchart TD
Unknown[unknown - top type] --> Any[any]
Any --> Number
Any --> BigInt
Any --> Boolean
Any --> String
Any --> Symbol
Any --> Object
Any --> Void
Any --> Null
Any --> Undefined
Object --> Array
Array --> Tuple
Object --> Function
Number --> Never[never - bottom type]
String --> Never
Boolean --> Never
Object --> Never
Tuple --> Never
unknownes el top type: todo es asignable a él, pero no permite operar sin acotar primero.neveres el bottom type: es subtipo de cualquier otro tipo y representa lo que nunca ocurre.
Los tipos especiales: null, undefined, void y never
Estos cuatro tipos modelan la ausencia de valor con matices distintos:
| Tipo | Significado |
|---|---|
null | Ausencia explícita de valor |
undefined | Variable que aún no recibió un valor |
void | Función que no tiene sentencia return |
never | Función que nunca retorna |
La distinción entre void y never es sutil pero importante. Una función void termina sin devolver nada útil; una función never no termina en absoluto, ya sea porque lanza una excepción o porque entra en un bucle infinito:
// void: termina, no retorna valor
function log(msg: string): void {
console.log(msg)
}
// never: nunca completa su ejecución
function fail(message: string): never {
throw new Error(message)
}
function loopForever(): never {
while (true) {}
}
Tip
never es especialmente útil en la verificación de exhaustividad: si un switch cubre todos los casos de una unión, la rama default puede asignar el valor a un never, y el compilador detectará en tiempo de compilación cualquier caso olvidado al ampliar la unión.
Varianza
Determinar si un tipo es sub o supertipo de otro no siempre es evidente, sobre todo al combinar estructuras y funciones. TypeScript dispone de una notación formal para razonar sobre estas relaciones:
A <: Bsignifica “Aes subtipo de, o el mismo tipo que,B”.A >: Bsignifica “Aes supertipo de, o el mismo tipo que,B”.
La varianza describe cómo se propagan estas relaciones cuando los tipos se anidan en estructuras (arreglos, objetos) o en firmas de función. Es el motivo por el que, por ejemplo, un arreglo de un subtipo no siempre es intercambiable con un arreglo de su supertipo: la mutabilidad introduce restricciones que el compilador debe respetar para mantener la solidez del sistema.
Conclusión
El sistema de tipos de TypeScript es una jerarquía gobernada por reglas de subtipado y varianza, con unknown como tipo superior y never como tipo inferior. Distinguir null, undefined, void y never, y comprender cómo B <: A permite sustituir un tipo por otro, te da una intuición precisa de por qué el compilador acepta o rechaza una asignación.
En el siguiente artículo aplicaremos metaprogramación con decoradores, funciones que extienden el comportamiento de clases, métodos y propiedades.


