TypeScriptGenerics and advanced types
keyof
Creates a union of the key names of a given object type.
Example
#TypeScript
interface Student {
name: string
level: number
points: number
}
type SortKey = keyof Student
// type SortKey = "name" | "level" | "points"
function sortBy(items: Student[], key: SortKey): string[] {
return [...items].sort((a, b) => (a[key] > b[key] ? -1 : 1)).map((s) => s.name)
}
const students: Student[] = [
{ name: 'Emma', level: 7, points: 1240 },
{ name: 'Jack', level: 9, points: 980 }
]
console.log(sortBy(students, 'points'))
console.log(sortBy(students, 'level'))Result
['Emma', 'Jack'] ['Jack', 'Emma']
Definition and usage
#The keyof operator takes an object type and returns a union of its keys as literal types. For { name: string; level: number } the result is "name" | "level".
This lets you type parameters that must be a field name, for example a sort column in a table. A typo in the field name gets caught by the compiler.
It’s often combined with typeof, to get the keys of an existing object: keyof typeof translations, and with mapped types, which iterate over all the keys of a type.
Syntax
#Syntax
type Keys = keyof TypeMore examples
#TypeScript
const labels = { html: 'HTML and CSS', py: 'Python' }
type CourseKey = keyof typeof labels
// type CourseKey = "html" | "py"
const key: CourseKey = 'py'
console.log(labels[key])Result
Python
Good practices
#- Always type “field name” type parameters through
keyof, notstring. - For objects with an index signature,
keyofreturnsstring | number, because numeric keys are allowed too.
Related entries
#Spotted a mistake or missing an example? Write to us.