Tipos literales en TypeScript
Los tipos literales (Literal Types) son una característica de TypeScript que representa valores específicos en lugar de tipos generales.
Permiten restringir el tipo de una variable a valores concretos, en lugar de tipos amplios como string, number, etc.
Esto proporciona un control de tipos más preciso y hace que el código sea más seguro en cuanto a tipos.
Diagrama SVG: Tipos literales
¿Por qué se necesitan los tipos literales?
En TypeScript, los tipos predeterminados como string y number son demasiado amplios.
A veces necesitamos un control de tipos más preciso. Por ejemplo, una variable solo puede tomar ciertos valores específicos.
Los tipos literales surgieron precisamente para resolver este tipo de problemas.
Explicación conceptual:Los tipos literales son valores concretos de tipos generales (string, number). Por ejemplo
"up"Sístringes un subtipo, y solo se le pueden asignar cadenas específicas.
Tipos literales de cadena
Los tipos literales de cadena restringen el valor de una variable a cadenas específicas.
Esto es muy útil cuando se necesita restringir una variable a solo ciertos valores fijos.
Ejemplo
// direction solo puede ser uno de cuatro valores específicos
var direction: "up" | "down" | "left" | "right";
// Correcto: asignar un valor del tipo literal
direction = "up";
// Error: asignar un valor que no está en la lista
// direction = "upup"; // ¡Error de compilación!
console.log("Dirección: " + direction);
// Usar un alias de tipo para crear un tipo literal reutilizable
// Definir un tipo de estado: solo puede ser uno de tres valores fijos
type Status = "pending" | "active" | "completed";
// Usar el alias de tipo
var currentStatus: Status = "active";
console.log("Estado: " + currentStatus);
Resultado de la ejecución:
方向: up Estado: active
Casos de uso:Los literales de cadena se usan a menudo para definir valores de enumeración, códigos de estado, opciones de configuración y otros escenarios que requieren restringir a valores específicos.
Tipos literales numéricos
Los tipos literales numéricos restringen el valor de una variable a números específicos.
Esto es muy útil cuando se necesitan usar valores numéricos específicos (como códigos de estado o códigos de error).
Ejemplo
// code solo puede ser uno de tres valores específicos
var code: 200 | 404 | 500;
// Correcto: asignar 200
code = 200;
// Error: asignar un valor que no está en la lista
// code = 301; // ¡Error de compilación!
console.log("Código de estado: " + code);
// Usar literales numéricos para simular enumeraciones
// Definir los días de la semana
type Weekday = 1 | 2 | 3 | 4 | 5 | 6 | 7;
// Solo se pueden asignar números entre 1 y 7
var today: Weekday = 1;
console.log("Hoy es el día: " + today);
Explicación:Los literales numéricos pueden reemplazar el uso de enumeraciones (enum) simples, especialmente cuando solo se necesitan unos pocos valores fijos.
Tipos literales booleanos
Los tipos literales booleanos restringen el valor de una variable a true o false.
En realidad, el tipo boolean en TypeScript es un alias de true | false.
Ejemplo
// isActive solo puede ser true o false
var isActive: true | false;
// Asignar true
isActive = true;
// En realidad, boolean es el tipo unión de true | false
// Por lo tanto, estas dos formas son equivalentes
var flag: boolean = true;
console.log("Activado: " + isActive);
Consejo:Aunque boolean ya es suficiente en la mayoría de los casos, cuando se necesita distinguir claramente entre los tipos true y false, se puede usar true o false como tipo.
Tipos literales de objeto
Los tipos literales de objeto pueden definir la estructura de un objeto y se puede usar el modificador readonly para hacer que las propiedades sean de solo lectura.
Esto es muy útil cuando se necesita crear objetos inmutables.
Ejemplo
// Especificar la estructura del objeto y los tipos de sus propiedades
type Point = {
// Coordenada x del punto
x: number;
// Coordenada y del punto
y: number;
};
// Usar el tipo literal de objeto
var p: Point = { x: 10, y: 20 };
console.log("Punto: " + JSON.stringify(p));
// Definir un tipo de objeto de solo lectura
// Usar el modificador readonly para hacer que las propiedades sean de solo lectura
type ReadonlyPoint = {
// Coordenada x de solo lectura
readonly x: number;
// Coordenada y de solo lectura
readonly y: number;
};
// Usar el tipo de objeto de solo lectura
var rp: ReadonlyPoint = { x: 1, y: 2 };
// Intentar modificar una propiedad de solo lectura causará un error
// rp.x = 3; // Error de compilación: las propiedades de solo lectura no se pueden modificar
console.log("Punto de solo lectura: " + JSON.stringify(rp));
Resultado de la ejecución:
点: {"x":10,"y":20}
只读点: {"x":1,"y":2}
Casos de uso:Los objetos de solo lectura se usan a menudo para definir objetos de configuración, objetos constantes y otros datos que no se desea modificar.
Tipos literales e inferencia de tipos
TypeScript infiere automáticamente tipos literales según la forma en que se declara la variable.
Las variables declaradas con const se infieren como tipos literales concretos, en lugar de tipos amplios.
Ejemplo
// TypeScript lo infiere como un tipo amplio
var name = "Alice"; // Tipo: string (porque var puede reasignarse)
var age = 25; // Tipo: number
var enabled = true; // Tipo: boolean
console.log("Nombre: " + name + ", Edad: " + age + ", Activado: " + enabled);
// Usar as const para crear un literal de solo lectura profunda
// El arreglo se convierte en una tupla de solo lectura, y los valores son tipos literales
var colors = ["red", "green", "blue"] as const;
// El tipo de colors se convierte en:
// readonly ["red", "green", "blue"]
// Acceder a los elementos del arreglo
console.log("Colores: " + colors[0]);
// Intentar modificar causará un error
// colors
Explicación:
as constEsto hace que el tipo se infiera como el tipo literal más específico y agrega el modificador readonly.
Tipos literales de plantilla
Los tipos literales de plantilla usan la sintaxis de plantillas de cadena de JavaScript para crear nuevos tipos.
Permiten generar tipos de cadena dinámicamente.
Ejemplo
// `on${string}` representa cualquier cadena que comience con "on"
type EventName = `on${string}`;
// Usar tipos literales de plantilla para definir nombres de manejadores
// Capitalize pone en mayúscula la primera letra de la cadena
type Handler = `handle${Capitalize<string>}`;
// Usar el tipo literal de plantilla
var event: EventName = "onClick";
var handler: Handler = "handleSubmit";
console.log("Evento: " + event);
console.log("Manejador: " + handler);
// Error: no cumple con el formato de plantilla
// var e: EventName = "click"; // Error de compilación: no comienza con "on"
Resultado de ejecución:
事件: onClick 处理器: handleSubmit
Tipos de utilidad integrados:Los tipos de literales de plantilla pueden usarse junto con los tipos de utilidad integrados como Uppercase, Lowercase, Capitalize, Uncapitalize.
Aplicación práctica: Acciones de Redux
Los tipos literales tienen una amplia aplicación en el desarrollo real.
A continuación se muestra cómo usar tipos literales para implementar acciones (Action) al estilo Redux.
Ejemplo
// Usa tipos de unión para definir diferentes tipos de Action
type Action =
// Action de tipo incremento, con payload de tipo numérico
| { type: "increment"; payload: number }
// Action de tipo decremento, con payload de tipo numérico
| { type: "decrement"; payload: number }
// Action de tipo reset, sin payload
| { type: "reset" };
// Función reducer que utiliza action
function reducer(action: Action): void {
// TypeScript infiere automáticamente el tipo específico de action a partir del valor de action.type
switch (action.type) {
case "increment":
// En esta rama, se infiere que action es { type: "increment"; payload: number }
console.log(Aumentar: + action.payload);
break;
case "decrement":
// En esta rama, se infiere que action es { type: "decrement"; payload: number }
console.log(Disminuir: + action.payload);
break;
case "reset":
// En esta rama, se infiere que action es { type: "reset" }
console.log(Restablecer);
break;
}
}
// Despachando diferentes tipos de Action
reducer({ type: "increment", payload: 5 });
reducer({ type: "reset" });
Resultado de ejecución:
增加: 5 重置
Uniones discriminadas:Este patrón se llama "unión discriminada" (Discriminated Union) y es la mejor práctica en TypeScript para manejar múltiples tipos relacionados.
Consideraciones
- Reducción de tipos:Al usar switch o if, TypeScript estrecha automáticamente los tipos literales.
- Alias de tipo:Se recomienda usar alias de tipo (type) para crear alias de tipos literales comunes.
- Inferencia de const:Las variables declaradas con const se infieren automáticamente como tipos literales.
- as const:Cuando se necesita solo lectura profunda, usa as const.
Mejores prácticas:Cuando sea necesario restringir variables a valores específicos, prioriza los tipos literales en lugar de las enumeraciones.
Resumen
Los tipos literales son una característica importante de TypeScript para lograr un control preciso de tipos.
- Literales de cadena:Restringido a cadenas específicas, como
"up" | "down" - Literales numéricos:Restringido a números específicos, como
1 | 2 | 3 - Literales booleanos:Restringido a true o false
- Literales de objeto:Al definir estructuras de objetos, se puede usar readonly.
- as const:Crear tipos literales de solo lectura en profundidad
- Literales de plantilla:Usar cadenas de plantilla para generar tipos dinámicamente
Otras extensionesAvanzado:La combinación de tipos literales con el patrón de uniones discriminadas puede lograr una sólida seguridad de tipos.