TypeScript 5.x: The Features That Make Type-Safe Code Actually Enjoyable

πŸ“… April 26, 2026

import Post from ’../../layouts/Post.astro’; export const prerender = true;

TypeScript 5.x brought a wave of improvements that make type-safe code actually enjoyable to write β€” not just theoretically correct.

1. Const Type Parameters

The generic constraint nobody knew they needed:

// Before: inference leaks beyond intended scope
function asArray<T>(value: T): T[] {
    return [value];
}
const result = asArray("hello"); // type: string[]
const force = asArray("hello" as const); // type: readonly ["hello"]

// After: const type parameter forces the inference you want
function asConstArray<const T>(value: T): readonly T[] {
    return [value];
}
const result = asConstArray("hello"); // type: readonly ["hello"]
const result2 = asConstArray([1, 2, 3]); // type: readonly number[]

This is huge for builder patterns, configuration objects, and any API where you want exact inference.

2. Decorators (Stable)

TypeScript 5.0 stabilized the ECMAScript decorators spec:

// Method decorator
function log(target: any, key: string, descriptor: PropertyDescriptor) {
    const original = descriptor.value;
    descriptor.value = function (...args: any[]) {
        console.log(`Calling ${key} with`, args);
        return original.apply(this, args);
    };
    return descriptor;
}

class UserService {
    @log
    createUser(name: string, email: string) {
        // ...
    }
}

No experimentalDecorators flag needed anymore. This works in Node 20+ and modern bundlers.

3. using Declarations (Resource Management)

Like await using in C#, automatic cleanup for resources:

// Auto-closes when scope ends
async function processFile(path: string) {
    const resource = await using file = await openFile(path);
    // work with file
} // file.close() called automatically, even on error

If you’re coming from Python’s with or C#β€˜s using, this finally brings it to TypeScript.

4. satisfies Operator β€” The Best Feature Nobody Talks About

// Before: union types lose specificity
const config = {
    port: 3000,
    host: "localhost",
    features: ["auth", "caching"],
};
config.port = "3000"; // no error? wrong!

// After: validate AND keep inference
const config = {
    port: 3000,
    host: "localhost",
    features: ["auth", "caching"],
} satisfies Config;

config.port = "3000"; // βœ… Error: string not assignable to number
config.features.push("logging"); // βœ… Fine β€” it's still string[]

satisfies validates against the type but preserves the literal inference. Game changer for configuration objects.

5. Type Parameters in Template Literal Types

type EventName<T extends string> = `on${Capitalize<T>}`;

type ClickEvent = EventName<"click">;    // "onClick"
type HoverEvent = EventName<"hover">;  // "onHover"

// Complex example: type-safe route params
type Route<T extends string> = `/api/${T}`;
type UserRoute = Route<"users">;         // "/api/users"
type PostRoute = Route<"posts/:id">;    // "/api/posts/:id"

6. Variadic Tuple Types β€” Finally Readable

// Before: ugly rest/spread
function merge<T extends any[], U extends any[]>(a: T, b: U): [...T, ...U] {
    return [...a, ...b];
}

// After: cleaner with explicit tuple labels
function merge<First extends unknown[], Second extends unknown[]>(
    a: First,
    b: Second
): [...First, ...Second] {
    return [...a, ...b];
}

const merged = merge(["a", "b"], [1, 2]);
// type: [string, string, number, number] β€” not (string | number)[]

The One to Actually Learn First

If you only pick one from this list: satisfies. It’s the most immediately useful, works in existing codebases without refactoring, and prevents a whole class of bugs in configuration objects.

// Every config object in your codebase should use this
const db = {
    host: "localhost",
    port: 5432,
    ssl: false,
} satisfies DatabaseConfig;
πŸ’‘

Enjoying the content? Here are tools I personally use and recommend:

  • 🌐 Hosting: Bluehost β€” what this blog runs on
  • πŸ›’ Tech Gear: My Amazon Store β€” keyboards, monitors, dev tools I use

Purchases through my links help keep this blog ad-free πŸ’™

Enjoyed this post?

Subscribe to the newsletter or follow on YouTube for more dev content.

🎬 Watch Shorts