Understanding Generics in Typescript
Generics in TypeScript allow you to create reusable and flexible components, such as functions, classes, or interfaces.
Generics allows you to work with a variety of data types while still preserving type safety.
Common Use Cases
- Collections: Arrays, Maps, Sets with specific types
- API Responses: Typed responses from API calls
- Utility Functions: Reusable functions that work with multiple types
- Higher-Order Components: In React and other frameworks
- State Management: Generic state containers
Basic Syntax
function identity<T>(arg: T): T {
return arg;
}
const num = identity<number>(42); // T is number
const str = identity("hello"); // T is inferred as string
Generic Functions
function logAndReturn<T>(value: T): T {
console.log(value);
return value;
}
const str = logAndReturn("test"); // type of result is string
const num = logAndReturn(5); // type of result is number
Generic Interfaces
interface Box<T> {
value: T;
}
const stringBox: Box<string> = { value: "hello" };
const numberBox: Box<number> = { value: 123 };
Generic Classes
class Stack<T> {
private items: T[] = [];
push(item: T): void {
this.items.push(item);
}
pop(): T | undefined {
return this.items.pop();
}
}
const numberStack = new Stack<number>();
numberStack.push(1);
numberStack.push(2);
numberStack.push(3);
console.log(numberStack.pop()); // 3
console.log(numberStack.pop()); // 2
console.log(numberStack.pop()); // 1
Generic Constraints
You can constrain generics to certain types using the extends
keyword:
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length);
return arg;
}
loggingIdentity("hello"); // OK - string has .length
loggingIdentity([1, 2, 3]); // OK - array has .length
loggingIdentity(42); // Error - number doesn't have .length
Summary
- Generics are a powerful feature in TypeScript that allow you to create reusable and flexible components that work with a variety of data types while still preserving type safety.
- Generics are defined using the
<T>
syntax, whereT
is a placeholder for the type. - Generics can be used with interfaces, classes, and functions.