Expanding on an example from Effective Typescript I can't tell if I'm running into a limitation of the type checker or my understanding.
Here's the example in its raw form from page 33
interface Point {
x: number
y: number
}
function sortBy<K extends keyof T, T>(vals: T[], key: K): T[] {
// ...
}
const pts: Point[] = [
{ x: 1, y: 1 },
{ x: 2, y: 0 },
]
console.log(sortBy(pts, "x"))
Here's my attempt to replace //... with something useful
interface Point {
x: number
y: number
}
function sortBy<K extends keyof T, T>(vals: T[], key: K): T[] {
// my solution
return vals.sort((a, b) => {
return b[key] - a[key] // Error: The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.ts(2362)
})
// end my solution
}
const pts: Point[] = [
{ x: 1, y: 1 },
{ x: 2, y: 0 },
]
console.log(sortBy(pts, "x"))
But if I replace with
return (b[key] as any) - (a[key] as any)
it works
What I can't figure out is why does the type checker think a[key] or b[key] could be anything other than a number, since a and b must be type Point, and key must be keyof Point.
If I write this without generics it works fine, which makes me think something hinky is going on here.
function sortBy(vals: Point[], key: "x" | "y"): Point[] {
return vals.sort((a, b) => {
return b[key] - a[key]
})
}