TypeScript 5 Updates

Latest features and improvements in TypeScript 5

🚀 TypeScript 5 New Features

TypeScript 5 brings significant improvements including decorators, const type parameters, better enums, and performance enhancements. These updates make TypeScript faster, more powerful, and easier to use while maintaining backward compatibility with existing code.


// TypeScript 5 decorator example
function logged(target: any, key: string) {
    console.log(`${key} was called`);
}
                                    

Major TypeScript 5 Features

✨

Decorators

ECMAScript decorators support

@sealed
class MyClass { }
🔒

Const Type Params

Preserve literal types

function foo<const T>(arr: T[]) {
  return arr;
}
📦

Better Enums

All enums are union enums

enum Status {
  Active,
  Inactive
}
âš¡

Performance

Faster compilation and checks

10-20% faster builds

🔹 Decorators (Stage 3)

TypeScript 5 supports ECMAScript decorators:

🔸 Class Decorator

function sealed(constructor: Function) {
    Object.seal(constructor);
    Object.seal(constructor.prototype);
}

@sealed
class BugReport {
    type = "report";
    title: string;
    
    constructor(title: string) {
        this.title = title;
    }
}

const bug = new BugReport("Critical Bug");
console.log(bug.title); // "Critical Bug"

🔸 Method Decorator

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

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

const calc = new Calculator();
calc.add(5, 3); 
// Logs: Calling add with [5, 3]
// Returns: 8

🔹 Const Type Parameters

Preserve literal types in generic functions:

🔸 Without Const

function makeArray<T>(arr: T[]) {
    return arr;
}

const arr1 = makeArray([1, 2, 3]);
// Type: number[]

🔸 With Const

function makeArray<const T>(arr: T[]) {
    return arr;
}

const arr2 = makeArray([1, 2, 3]);
// Type: readonly [1, 2, 3]

const colors = makeArray(["red", "green", "blue"]);
// Type: readonly ["red", "green", "blue"]

🔹 All Enums Are Union Enums

Better type checking for enums:

enum Status {
    Active = "ACTIVE",
    Inactive = "INACTIVE",
    Pending = "PENDING"
}

function setStatus(status: Status) {
    console.log(`Status set to: ${status}`);
}

setStatus(Status.Active);  // OK
// setStatus("ACTIVE");    // Error in TS 5

// Enum as type
type ActiveStatus = Status.Active | Status.Pending;

function processActive(status: ActiveStatus) {
    if (status === Status.Active) {
        console.log("Processing active");
    } else {
        console.log("Processing pending");
    }
}

🔹 Supporting Multiple Config Files

Extend from multiple configuration files:

// tsconfig.json
{
  "extends": ["./base.json", "./strict.json"],
  "compilerOptions": {
    "outDir": "./dist"
  }
}

🔹 Better Module Resolution

New moduleResolution options:

{
  "compilerOptions": {
    "moduleResolution": "bundler",
    "module": "esnext",
    "target": "esnext"
  }
}

🔸 Import Attributes

// Import JSON with attributes
import data from "./data.json" with { type: "json" };

// Import CSS modules
import styles from "./styles.css" with { type: "css" };

console.log(data.name);
console.log(styles.container);

🔹 Improved Type Narrowing

Smarter type inference in control flow:

function processValue(value: string | number | null) {
    // TypeScript 5 better understands this
    if (typeof value === "string") {
        console.log(value.toUpperCase());
    } else if (typeof value === "number") {
        console.log(value.toFixed(2));
    } else {
        console.log("Value is null");
    }
}

// Better array filtering
const mixed: (string | number)[] = [1, "two", 3, "four"];
const strings = mixed.filter((x): x is string => typeof x === "string");
// Type: string[]

🔹 Switch (true) Narrowing

Type narrowing in switch statements:

function getArea(shape: { kind: "circle"; radius: number } | { kind: "square"; size: number }) {
    switch (true) {
        case shape.kind === "circle":
            return Math.PI * shape.radius ** 2;
        case shape.kind === "square":
            return shape.size ** 2;
        default:
            return 0;
    }
}

const circle = { kind: "circle" as const, radius: 5 };
const square = { kind: "square" as const, size: 4 };

console.log(getArea(circle)); // 78.54
console.log(getArea(square)); // 16

🔹 Performance Improvements

TypeScript 5 is faster:

  • 10-20% faster compilation times
  • Reduced memory usage during type checking
  • Faster IDE response times
  • Optimized module resolution
  • Better caching for incremental builds

🔹 JSDoc @satisfies

Use satisfies in JSDoc comments:

// TypeScript
const config = {
    url: "https://example.com",
    port: 8080
} satisfies Config;

// JavaScript with JSDoc
/** @satisfies {Config} */
const config = {
    url: "https://example.com",
    port: 8080
};

🔹 Practical Example

Combining TypeScript 5 features:

// Using decorators and const type parameters
function validate(target: any, propertyKey: string) {
    console.log(`Validating ${propertyKey}`);
}

class User {
    @validate
    name: string;
    
    @validate
    email: string;
    
    constructor(name: string, email: string) {
        this.name = name;
        this.email = email;
    }
}

// Using const type parameters
function createConfig<const T extends Record<string, any>>(config: T) {
    return config;
}

const appConfig = createConfig({
    apiUrl: "https://api.example.com",
    timeout: 5000,
    retries: 3
} as const);

// Type is preserved exactly
type ConfigType = typeof appConfig;
// {
//   readonly apiUrl: "https://api.example.com";
//   readonly timeout: 5000;
//   readonly retries: 3;
// }

const user = new User("Alice", "[email protected]");
console.log(user.name);
console.log(appConfig.apiUrl);

🔹 Migration Tips

Upgrading to TypeScript 5:

  1. Update TypeScript: npm install -D typescript@latest
  2. Review breaking changes in release notes
  3. Update tsconfig.json for new features
  4. Test your codebase thoroughly
  5. Enable new strict options gradually
  6. Update IDE extensions for best experience

🧠 Test Your Knowledge

What new feature does TypeScript 5 add for preserving literal types?