TypeScript Generics: Functions, Interfaces, and Constraints
Generics enable reusable, type-safe code. Here's what interviews test — from basic generic functions to constraints.
Generic functions
Generics create functions that work with multiple types while preserving type information.
// Without generics — loses type information
function identity(value: any): any {
return value;
}
// With generics — type is preserved
function identity<T>(value: T): T {
return value;
}
const str = identity("hello"); // type: string
const num = identity(42); // type: number
// Multiple type parameters
function pair<A, B>(first: A, second: B): [A, B] {
return [first, second];
}
const result = pair("Alice", 30); // type: [string, number]Generic interfaces and types
Generics also work with interfaces and type aliases.
// Generic interface
interface ApiResponse<T> {
data: T;
status: number;
message: string;
}
type UserResponse = ApiResponse<User>;
type UserListResponse = ApiResponse<User[]>;
// Generic Stack
interface Stack<T> {
push(item: T): void;
pop(): T | undefined;
peek(): T | undefined;
isEmpty(): boolean;
}
// Generic Promise wrapper
async function fetchJson<T>(url: string): Promise<T> {
const res = await fetch(url);
return res.json() as T;
}Constraints with extends
Constraints restrict which types can be used as a type parameter.
// T must have a length property
function longest<T extends { length: number }>(a: T, b: T): T {
return a.length >= b.length ? a : b;
}
longest("hello", "hi"); // OK — strings have length
longest([1, 2, 3], [1, 2]); // OK — arrays have length
longest(1, 2); // Error — numbers have no length
// keyof constraint
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const user = { name: "Alice", age: 30 };
getProperty(user, "name"); // type: string
getProperty(user, "age"); // type: number
getProperty(user, "email"); // Error: "email" not in userConditional types
Conditional types express "if T extends X, then Y, else Z" at the type level.
type IsArray<T> = T extends any[] ? true : false; type A = IsArray<number[]>; // true type B = IsArray<string>; // false // NonNullable removes null and undefined type NonNullable<T> = T extends null | undefined ? never : T; type C = NonNullable<string | null>; // string // Extracting return type type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never; type D = ReturnType<() => string>; // string
Exam tip
The K extends keyof T pattern is the most common advanced TypeScript interview question. It creates a function that accepts only valid property names — TypeScript guarantees you can't access a property that doesn't exist.
Think you're ready? Prove it.
Take the free TypeScript readiness test. Get a score, topic breakdown, and your exact weak areas.
Take the free TypeScript test →Free · No sign-up · Instant results