TypeScript continues to evolve rapidly, and the 5.x series has introduced some of the most impactful features since generics. This comprehensive guide covers every major feature with real-world code examples.
1. The satisfies Operator
The satisfies operator validates that an expression matches a type without widening it. This is a game-changer for configuration objects.
type Colors = 'red' | 'green' | 'blue';
type ColorConfig = Record<Colors, string | [number, number, number]>;
const palette = {
red: [255, 0, 0],
green: '#00ff00',
blue: [0, 0, 255],
} satisfies ColorConfig;
// ✅ TypeScript knows palette.green is a string
palette.green.toUpperCase();
// ✅ TypeScript knows palette.red is a tuple
palette.red[0]; // number
2. Const Type Parameters
Adding const to a type parameter infers the most specific (literal) type without needing as const at the call site.
function createRoutes<const T extends readonly string[]>(routes: T) {
return routes;
}
// Type is readonly ["home", "about", "contact"]
const routes = createRoutes(["home", "about", "contact"]);
// Without const: string[]
3. Decorators (Stage 3 Standard)
TypeScript 5.0+ supports the TC39 Stage 3 decorators standard — no experimental flags needed.
function log(originalMethod: any, context: ClassMethodDecoratorContext) {
return function (...args: any[]) {
console.log(`Calling ${String(context.name)} with`, args);
return originalMethod.apply(this, args);
};
}
class UserService {
@log
getUser(id: string) {
return fetch(`/api/users/${id}`);
}
}
4. Isolated Declarations
A new compiler option that enables parallel, tool-independent .d.ts generation — speeding up monorepo builds dramatically.
// tsconfig.json
{
"compilerOptions": {
"isolatedDeclarations": true,
"declaration": true
}
}
// All exported functions need explicit return types
export function add(a: number, b: number): number {
return a + b;
}
5. Using Declarations (Explicit Resource Management)
The using keyword enables automatic cleanup of resources — like Python's with or C#'s using.
class DatabaseConnection implements Disposable {
[Symbol.dispose]() {
console.log('Connection closed');
}
}
function queryDatabase() {
using conn = new DatabaseConnection();
// conn is automatically disposed when scope exits
return conn.query('SELECT * FROM users');
}
6. Improved Type Narrowing
// Switch(true) narrowing
function handleValue(value: string | number | boolean) {
switch (true) {
case typeof value === 'string':
return value.toUpperCase(); // TypeScript knows it's string
case typeof value === 'number':
return value.toFixed(2); // TypeScript knows it's number
default:
return value; // boolean
}
}
satisfies and const type params alone will change how you write config-heavy code. Upgrade your tsconfig and start using these features today.