TypeScript Tipos especiales: never, void, unknown, any
TypeScript tiene cuatro tipos especiales: never, void, unknown y any.
Desempeñan un papel importante en el sistema de tipos; comprender sus diferencias es fundamental para escribir código con seguridad de tipos.
Diagrama SVG: Comparación de tipos especiales
¿Por qué se necesitan tipos especiales?
El sistema de tipos de TypeScript es muy potente; además de los tipos convencionales, proporciona cuatro tipos especiales para manejar escenarios específicos.
Comprender las diferencias entre estos cuatro tipos especiales nos ayuda a escribir código tipado más seguro y preciso.
Explicación del concepto:never, void, unknown y any son tipos especiales de TypeScript; cada uno tiene diferentes significados y casos de uso.
Tipo never
never representa un tipo que nunca retorna. Normalmente se usa para funciones que lanzan excepciones o tienen bucles infinitos.
Ejemplo
// La función nunca retorna normalmente, siempre lanza un error
function throwError(message: string): never {
throw new Error(message);
}
// Función con bucle infinito
// La función nunca retorna, el programa se ejecutará indefinidamente
function infiniteLoop(): never {
while (true) {
console.log("Ejecutando...");
}
}
// never es un subtipo de todos los tipos
// Esto significa que never se puede asignar a cualquier tipo
var neverValue: never;
var num: number = neverValue; // Correcto: never es un subtipo de number
console.log("never asignado a number: " + num);
Resultado de ejecución:
never 赋值给 number: undefined
Importante:never es un subtipo de todos los tipos, lo que significa que never se puede asignar a cualquier tipo, pero ningún tipo se puede asignar a never (excepto never mismo).
Tipo void
void indica que no hay valor de retorno; normalmente se usa para declarar funciones sin sentencia return.
Ejemplo
// Después de ejecutarse, la función no devuelve ningún valor
function logMessage(message: string): void {
console.log("Log: " + message);
// Sin sentencia return, o return undefined
}
logMessage("Hello");
// Variable void (rara vez usada)
// Solo se puede asignar undefined
var empty: void = undefined;
console.log("Variable void: " + empty);
Resultado de ejecución:
日志: Hello void 变量: undefined
Explicación:void en realidad es muy similar a undefined; se usa principalmente en la declaración del tipo de retorno de una función, indicando que la función no tiene valor de retorno.
Tipo unknown
unknown es un any seguro. Al usar unknown, primero se debe realizar una comprobación de tipos.
Ejemplo
// Este es el any "seguro"
var value: unknown = "hello";
value = 42;
value = true;
// Un tipo desconocido no se puede asignar directamente a otros tipos
// Si se descomenta la siguiente línea, el compilador mostrará un error
// var str: string = value;
// Es necesario realizar una comprobación de tipos antes de poder asignarlo
if (typeof value === "string") {
// TypeScript sabe que value es de tipo string
var str: string = value;
console.log("Longitud de la cadena: " + str.length);
}
Resultado de ejecución:
字符串长度: 5
Seguridad:unknown obliga a realizar una comprobación de tipos antes de usar el valor, lo cual protege la seguridad de tipos. Al manejar datos de origen desconocido, se debe usar unknown en lugar de any.
Tipo any
any omite por completo la comprobación de tipos y se puede asignar a cualquier tipo. Es el tipo menos seguro de TypeScript.
Ejemplo
// Omite por completo la comprobación de tipos
var anything: any = "hello";
anything = 42;
anything = true;
// any se puede asignar a cualquier tipo
// Esto destruye la seguridad de tipos
var str: string = anything;
var num: number = anything;
console.log("Cadena: " + str);
console.log("Número: " + num);
// Un objeto de tipo any puede llamar a cualquier método
// El compilador no mostrará error, pero en tiempo de ejecución puede fallar
var obj: any = {};
obj.foo(); // No mostrará error, pero el método foo realmente no existe
obj.bar = "value";
Advertencia:El tipo any omite por completo la comprobación de tipos de TypeScript; se debe evitar su uso en la medida de lo posible. Si es imprescindible usarlo, hay que asegurarse de que el valor sea del tipo correcto.
Comparación any vs unknown
any y unknown pueden aceptar cualquier tipo, pero su seguridad es completamente diferente.
| Característica | any | unknown |
|---|---|---|
| Acepta cualquier tipo | ✓ Sí | ✓ Sí |
| Asignación directa a otros tipos | ✓ Sí | ✗ No (requiere comprobación) |
| Llamada directa a métodos | ✓ Sí | ✗ No (requiere comprobación) |
| Seguridad de tipos | ✗ Ninguna | ✓ Sí |
Sugerencia:Al manejar datos de tipo desconocido, se debe priorizar el uso de unknown en lugar de any; esto fuerza la comprobación de tipos.
never vs void
never y void se usan ambos como tipo de retorno de funciones, pero sus significados son completamente diferentes.
| Característica | never | void |
|---|---|---|
| Significado | Nunca retorna | Sin valor de retorno |
| Usado en funciones | Lanza excepción / bucle infinito | Función normal sin valor de retorno |
| Se puede asignar a otros tipos | ✓ Sí (subtipo) | Solo se puede asignar a void/any |
Diferencia clave:never indica que la función nunca retorna de forma normal (o lanza una excepción, o entra en un bucle infinito); void indica que la función termina su ejecución normalmente pero no devuelve ningún valor.
Aplicación práctica: Exhaustive Check
Un uso importante del tipo never es realizar una comprobación exhaustiva, asegurando que todos los casos posibles hayan sido manejados.
Ejemplo
type Shape = { kind: "circle", radius: number }
| { kind: "square", side: number };
// Calcular el área de la forma
function area(shape: Shape): number {
switch (shape.kind) {
case "circle":
return Math.PI * shape.radius ** 2;
case "square":
return shape.side ** 2;
default:
// La rama default debería manejar todos los casos no previstos
// Si se agrega un nuevo tipo Shape pero se olvida manejarlo, el compilador mostrará un error
var _exhaustive: never = shape;
return _exhaustive;
}
}
var circle = { kind: "circle" as const, radius: 5 };
var square = { kind: "square" as const, side: 4 };
console.log("Área del círculo: " + area(circle).toFixed(2));
console.log("Área del cuadrado: " + area(square));
Resultado de ejecución:
圆形面积: 78.54 正方形面积: 16
Exhaustive Check:Este patrón asegura que al agregar un nuevo tipo a la unión, si se olvida manejarlo en el switch, el compilador mostrará un error, porque el nuevo tipo no se puede asignar a never.
Consideraciones
- never es un subtipo:never se puede asignar a cualquier tipo, pero ningún tipo se puede asignar a never
- void vs undefined:En JavaScript, void y undefined son básicamente equivalentes
- unknown requiere comprobación:Antes de usar un valor de tipo unknown, se debe realizar una verificación de tipo.
- Evitar any:Intenta no usar any, prioriza unknown.
Mejores prácticas:Nivel de seguridad de tipos de mayor a menor: never > void > unknown > any. Usa tipos más seguros siempre que sea posible.
Resumen
Comprender estos cuatro tipos especiales es muy importante para escribir código TypeScript de alta calidad.
- never:Nunca retorna, se usa para exhaustive check, es subtipo de todos los tipos.
- void:Sin valor de retorno, se usa para funciones normales sin valor de retorno.
- unknown:Tipo arbitrario seguro, se debe realizar una verificación de tipo antes de usarlo.
- any:Omite toda verificación de tipos, debe evitarse en la medida de lo posible.
Otras extensionesSugerencias:Al escribir código, prioriza tipos más estrictos. Usa unknown para datos desconocidos, void para funciones sin valor de retorno, y never cuando se necesite una comprobación exhaustiva.