Reading — step 1 of 5
Learn
~1 min readGenerics and Unions
Generics parameterize types over types. Most useful when a function or class works with values whose types you don't want to fix:
function firstOrDefault<T>(list: T[], fallback: T): T {
return list.length > 0 ? list[0] : fallback;
}
const n = firstOrDefault([1, 2, 3], 0); // T inferred as number
const s = firstOrDefault<string>([], "default"); // T explicit
Generic classes:
class Box<T> {
constructor(public value: T) {}
map<U>(f: (x: T) => U): Box<U> {
return new Box(f(this.value));
}
}
const b = new Box(5).map(n => n * 2).map(n => `value: ${n}`);
// Box<string> { value: 'value: 10' }
Constraints — restrict T to types with certain shape:
interface Lengthy { length: number; }
function longest<T extends Lengthy>(a: T, b: T): T {
return a.length >= b.length ? a : b;
}
longest("hello", "hi"); // string is Lengthy ✓
longest([1, 2, 3], [4]); // arrays have length ✓
// longest(5, 10); // number doesn't have length — compile error
Multiple type parameters:
function pair<A, B>(a: A, b: B): [A, B] {
return [a, b];
}
Generics are erased at runtime — they exist only at compile time. Same as Java's type erasure.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…