#typescript
#generics
#advanced
Day 16: Generic Constraints
Limiting the “Any”
Welcome to Day 16! Yesterday we saw how Generics let you pass anything. But what if we need our generic to have a specific property, like .length?
function logLength<T>(arg: T): T {
// console.log(arg.length); // Error: Property 'length' does not exist on type 'T'.
return arg;
}
TypeScript complains because T could be a number, which doesn’t have .length.
The extends Keyword
We can constrain T to say “T must look at least like this interface”.
interface Lengthwise {
length: number;
}
function logLength<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // OK!
return arg;
}
Now usage:
logLength("Hello"); // OK (string has length)
logLength([1, 2, 3]); // OK (array has length)
// logLength(10); // Error: number doesn't have length
Using Keyof Constraint
A common pattern is ensuring a key exists on an object.
function getProperty<T, K extends keyof T>(obj: T, key: K) {
return obj[key];
}
let x = { a: 1, b: 2, c: 3 };
getProperty(x, "a"); // OK
// getProperty(x, "m"); // Error: "m" is not a key of x
Challenge for Today
- Create a generic function
merge<T, U>(obj1: T, obj2: U). - Constrain
TandUto be objects (useextends objector similar). - The function should return the intersection
T & U. - Implement it using
Object.assignor spread syntax.
See you on Day 17 for Type Guards - checking types at runtime!