Generic Constraints
Constraints
π¨βπΌ Sometimes you need to limit what types can be used with a generic. For
example, a function that accesses
.length only works with types that have a
length property.// β Error: Value might not have .length
function logLength<Value>(value: Value) {
console.log(value.length)
}
// β
Constrain Value to types with length
function logLength<Value extends { length: number }>(value: Value) {
console.log(value.length) // Safe!
}
logLength('hello') // β
strings have length
logLength([1, 2, 3]) // β
arrays have length
logLength(42) // β Error: number has no length
Use
extends to add constraints.π¨ Open
and:
- Implement
getIdβ accepts objects that haveid: stringand returns thatid - Implement
getPropertyβ takes an object and a key of that object, returns the value at that key with the correct type - Implement
mergeβ takes two objects and returns one object with properties from both; when keys overlap, the second argument wins - Export
getId,getProperty, andmergeby name
Completion criteria
- Named exports:
getId,getProperty,merge getId({ id: '1', name: 'Alice' })β'1'getProperty(user, 'email')returns the email stringmerge({ a: 1, b: 2 }, { b: 3, c: 4 })β{ a: 1, b: 3, c: 4 }
This is a small preview of type operators. We'll dive deeper into these in
the Advanced TypeScript workshop.
keyof ObjectType produces a union of all property names of type ObjectType.
For example, if ObjectType is { name: string; age: number }, then
keyof ObjectType is 'name' | 'age'.ObjectType[Key] is an indexed access type - it gives you the type of
property Key on type ObjectType. If ObjectType is { name: string } and Key
is 'name', then ObjectType[Key] is string.