Skip to content

TypeScript 5.x: las features que cambian cómo escribes código

Andrés Ujpán

TypeScript sigue evolucionando a un ritmo acelerado. Las versiones 5.x trajeron cambios que van más allá de mejoras de rendimiento: redefinen patrones que llevamos años usando.

Table of contents

Open Table of contents

Decoradores estándar (TC39 Stage 3)

Por fin. Después de años con la versión experimental, TypeScript 5.0 adoptó los decoradores estándar de TC39. La sintaxis es similar pero la semántica cambió bastante.

// Decorador de clase — antes (experimental)
@sealed
class OldClass { ... }

// Decorador estándar — TS 5.x
function logged<T extends new (...args: unknown[]) => unknown>(
  target: T,
  _ctx: ClassDecoratorContext,
) {
  return class extends target {
    constructor(...args: unknown[]) {
      super(...args);
      console.log(`[LOG] Instancia de ${target.name} creada`);
    }
  };
}

@logged
class UserService {
  constructor(private db: Database) {}
}decorators.ts

Decoradores de método y accesor

function measure(_target: unknown, ctx: ClassMethodDecoratorContext) {
  const name = String(ctx.name);
  return function (this: unknown, ...args: unknown[]) {
    const start = performance.now();
    const result = (this as Record<string, Function>)[name](...args); 
    const result = Reflect.apply(
      _target as Function,
      this,
      args 
    ); 
    console.log(`${name} tardó ${performance.now() - start}ms`);
    return result;
  };
}

class ReportService {
  @measure
  async generatePDF(id: string) {
    /* ... */
  }
}method-decorator.ts

const Type Parameters

Antes necesitabas as const en cada llamada para inferir tuplas literales. Ahora puedes declararlo en el genérico:

// Antes: inferido como string[]
function head<T>(arr: T[]) {
  return arr[0];
}
head(["a", "b"]); // tipo: string

// Ahora: inferido como el literal exacto
function head<const T extends readonly unknown[]>(arr: T) {
  return arr[0];
}
head(["a", "b"] as const); // tipo: "a"
head(["a", "b"]); // tipo: "a"  ← funciona sin as constconst-type-params.ts

satisfies operator (consolidado)

Introducido en 4.9 pero ya es parte del flujo diario. Permite validar que un valor satisface un tipo sin “ensancharlo”:

type Palette = {
  red: [number, number, number] | string;
  green: [number, number, number] | string;
  blue: [number, number, number] | string;
};

const palette = {
  red: [255, 0, 0],
  green: "#00ff00",
  blue: [0, 0, 255],
} satisfies Palette; 

// Ahora TypeScript sabe que red es una tupla, no string
palette.red.at(0); // ✓ — antes daba errorsatisfies.ts

Mejoras en inferencia de infer

// Extraer el tipo de retorno filtrado por constraint
type ReturnIfString<T> = T extends () => infer R extends string
  ? R
  : never;

type A = ReturnIfString<() => "hello">; // "hello"
type B = ReturnIfString<() => number>;  // neverinfer-extends.ts

Rendimiento: modo --incremental y --composite

TS 5.x optimizó las builds incrementales. En proyectos grandes la mejora puede ser de hasta :

{
  "compilerOptions": {
    "composite": true,
    "incremental": true,
    "tsBuildInfoFile": ".tsbuildinfo",
    "moduleResolution": "bundler"
  }
}tsconfig.json

Consejo: combina composite con referencias de proyecto (references) para monorepos. Cada paquete compilará sólo lo que cambió.

Resumen rápido

FeatureVersiónImpacto
Decoradores estándar5.0Alto — reemplaza experimental
const type params5.0Medio — menos as const
satisfies4.9 / consolidado en 5.xAlto — tipado más expresivo
infer ... extends5.xMedio — tipos condicionales más precisos
Build incremental mejorado5.xAlto en monorepos
Editar este post
Anterior
Agentes IA Autónomos: la nueva forma de construir software en 2026
Siguiente
Rust para desarrolladores JavaScript: el salto que vale la pena