IT

Guía Práctica de Características Nuevas de TypeScript 5 — Operador Satisfies y Decoradores

USD/JPY分散は、為替急変局面で一方通貨の過大シェアを防ぎ、月次の再バランスと上限規則で感情的な一括投資を抑える実践設計です。

Guía Práctica de Características Nuevas de TypeScript 5 — Operador Satisfies y Decoradores

> Resumen Clave TypeScript 5.0–5.3 (2026) introduce operador satisfies para validación de tipo sin asignación, decoradores estables para inyección de dependencia, const type parameters para genéricos constantes, y mejoras en JSDoc. Satisfies es la característica más importante, permitiendo verificar cumplimiento de tipo mientras se preserva tipo literal.

## Operador Satisfies — La Característica Más Importante

### Antes de TypeScript 5 (Problema)

```typescript interface User { name: string; age: number; }

const user: User = { name: "Alice", age: 30, // ❌ Error — campo extra no permitido email: "[email protected]", }; ```

Problema: Si escribes : User, pierdes el tipo literal de las propiedades:

``typescript const user: User = { name: "Alice", age: 30 }; console.log(user.name); // Tipo: string (genérico) // ¿No puedes hacer: typeof user.name === "Alice" para type guard? ``

### Después de TypeScript 5 (Solución — Satisfies)

```typescript const user = { name: "Alice", age: 30, } satisfies User;

console.log(user.name); // Tipo: "Alice" (literal preservado) // ✅ Ahora puedes hacer: typeof user.name === "Alice" ```

### Ventajas de Satisfies

1. Verifica Cumplimiento — Asegura que el objeto implementa la interfaz 2. Preserva Tipo Literal — El tipo de cada propiedad se mantiene literal ("Alice", no string) 3. Evita Sobre-asignación — No permite campos extra 4. Mejor Inferencia — El compilador infiere tipos más específicos

### Casos de Uso Prácticos

#### Caso 1: Configuración de Aplicación

```typescript interface Config { apiUrl: string; port: number; debug: boolean; }

const config = { apiUrl: "https://api.example.com", port: 3000, debug: process.env.NODE_ENV === "development", } satisfies Config;

// Beneficio: Puedes hacer union types sobre literal type ApiUrl = typeof config.apiUrl; // "https://api.example.com" ```

#### Caso 2: Rutas Tipadas

```typescript interface Route { path: string; method: "GET" | "POST"; handler: (req: any) => any; }

const routes = [ { path: "/users", method: "GET", handler: () => "list users", }, { path: "/users/:id", method: "POST", handler: (req) => "create user", }, ] satisfies Route[];

// Beneficio: Autocomplete en método + validación routes[0].method; // Tipo: "GET" (literal) ```

#### Caso 3: Registro de Constantes

```typescript interface LogLevel { level: "debug" | "info" | "warn" | "error"; color: "blue" | "green" | "yellow" | "red"; }

const LOG_LEVELS = { DEBUG: { level: "debug", color: "blue" }, INFO: { level: "info", color: "green" }, WARN: { level: "warn", color: "yellow" }, ERROR: { level: "error", color: "red" }, } satisfies Record;

// Beneficio: Acceso tipado a propiedades anidadas console.log(LOG_LEVELS.DEBUG.level); // Tipo: "debug" ```


## Decoradores — Inyección de Dependencia Real

### Sintaxis de Decorador

```typescript @decorator class MyClass { @propertyDecorator prop: string;

@methodDecorator method() {} } ```

### Decorador de Clase (Inyección de Dependencia)

``typescript function Injectable(target: Function) { // target = MyService class console.log(${target.name} es inyectable`); }

@Injectable class MyService { getData() { return "data"; } } ```

### Decorador de Propiedad

``typescript function Validate(pattern: RegExp) { return function (target: any, propertyKey: string) { let value = target[propertyKey]; Object.defineProperty(target, propertyKey, { get() { return value; }, set(newVal: string) { if (!pattern.test(newVal)) { throw new Error(${propertyKey} no cumple patrón`); } value = newVal; }, }); }; }

class User { @Validate(/^[\w.-]+@[\w.-]+\.\w+$/) email: string; }

const user = new User(); user.email = "invalid"; // ❌ Error en validación ```

### Decorador de Método (Logging)

``typescript function Log(target: any, propertyKey: string, descriptor: PropertyDescriptor) { const originalMethod = descriptor.value; descriptor.value = function (...args: any[]) { console.log(Llamando ${propertyKey} con`, args); return originalMethod.apply(this, args); }; }

class Calculator { @Log add(a: number, b: number) { return a + b; } }

const calc = new Calculator(); calc.add(2, 3); // Logs: Llamando add con [2, 3] ```

### Decorador Parametrizado (Factory)

``typescript function MinLength(min: number) { return function Validate(target: any, propertyKey: string) { Object.defineProperty(target, propertyKey, { set(newVal: string) { if (newVal.length < min) { throw new Error(${propertyKey} debe tener mínimo ${min} caracteres`); } }, }); }; }

class Account { @MinLength(8) password: string; } ```


## Const Type Parameters — Genéricos Constantes

### Problema Anterior

```typescript function identity(x: T): T { return x; }

const result = identity("hello"); // result tiene tipo: string (no "hello") ```

### Solución — Const Type Parameter

```typescript function identity(x: T): T { return x; }

const result = identity("hello"); // result tiene tipo: "hello" (literal preservado) ```

### Caso de Uso: Builder Pattern

```typescript function createObject>(obj: T): T { return obj; }

const config = createObject({ name: "MyApp", version: "1.0", debug: true, });

// Tipo: { readonly name: "MyApp"; readonly version: "1.0"; readonly debug: true } ```


## Mejoras en JSDoc — Soporte de Tipos en Comentarios

### JSDoc Tipo Union

``typescript /* Calcula la suma de dos números @param {number | string} a - Primer número o cadena numérica @param {number | string} b - Segundo número o cadena numérica @returns {number} La suma / function add(a, b) { return Number(a) + Number(b); } ``

### JSDoc Genéricos

``typescript /* Filtra matriz por predicado @template T @param {T[]} arr - Array a filtrar @param {(item: T) => boolean} predicate - Función de filtro @returns {T[]} Array filtrado */ function filter(arr, predicate) { return arr.filter(predicate); } ``


## Mejoras en Inferencia de Tipos

### Asignación más Inteligente

```typescript // TypeScript 5 infiere tipos más precisos const obj = { a: 10, b: "hello", c: () => "world", };

// Tipos: // a: number (antes sería type number) // b: string // c: () => string ```

### Mejor Narrowing en Discriminados

```typescript type Shape =

{ type: "circle"; radius: number
{ type: "square"; side: number }

function area(shape: Shape) { if (shape.type === "circle") { // shape es { type: "circle"; radius: number } return Math.PI shape.radius * 2; } } ```


## Preguntas Frecuentes

### P1: ¿Cuándo usar satisfies vs :?

R: Usa satisfies cuando necesites preservar tipos literales. Usa : cuando necesites aceptar cualquier valor del tipo.

```typescript // satisfies: Preserva "Alice" const user1 = { name: "Alice" } satisfies User; // Tipo de name: "Alice"

// : Amplía a string const user2: User = { name: "Alice" }; // Tipo de name: string ```

### P2: ¿Los decoradores están estables?

R: Sí, desde TypeScript 5.0. Requiere experimentalDecorators: false en tsconfig.json (el predeterminado en TS 5+).

### P3: ¿Cuál es el rendimiento de const type parameters?

R: Sin costo en tiempo de ejecución. Solo afecta la compilación (mejora la inferencia).

### P4: ¿Debo migrar mi código existente a satisfies?

R: No urgente, pero recomendado para nuevas configuraciones y objetos constantes donde quieras preservar tipos literales.

### P5: ¿JSDoc es mejor que anotaciones de tipo?

R: No. JSDoc sin TypeScript es más débil. Usa JSDoc solo si no puedes usar TypeScript en un archivo.

### P6: ¿Cuál es la nueva característica más importante para productividad?

R: Satisfies. Reduce el uso de type assertions y type guards innecesarios.

🔧 Related Free Tools

Relacionado