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 Fondo Título Comparación de los cuatro tipos especiales any Cualquier tipo Omite la comprobación de tipos Sin seguridad unknown Cualquier tipo seguro Requiere comprobación para usar Con seguridad void Sin valor de retorno Usado en funciones Puede devolver undefined never Nunca retorna Lanza excepción / bucle Subtipo de todos los tipos Etiqueta de flecha Parte inferior: Nivel de seguridad de tipos Nivel de seguridad de tipos Nivel 1 any (el más bajo) Omite completamente la comprobación de tipos Nivel 2 unknown Requiere comprobación de tipos antes de usar Nivel 3 void Función sin valor de retorno Nivel 4 never (el más alto) El más estricto, el más seguro

¿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

// Función que lanza una excepción
// 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

// Función sin valor de retorno
// 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

// unknown acepta cualquier tipo
// 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

// any puede ser de cualquier tipo
// 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

// Definir el tipo unión de formas
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.

Sugerencias: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.

Otras extensiones