Issue
I got a simple function with an array of objects. On this array there will always be at least one string
property.
In the body I want to dinamically be able to select that string
by key
and order with localCompare
.
The problem is that the properties can have numbers
and when doing localCompare TS complains.
;(() => {
type entries = {
[key: string]: string | number
}
const data: entries[] = [
{ key: 'bbb', number: 1 },
{ key: 'aaa', number: 2}
]
// Let's imagine index comes as a parameter
const index = 'key'
const order: entries[] = data.sort((a, b) => a[index].localeCompare(b[index]))
console.log(order)
})()
Solution
Based on your comments, I think you’re saying that you know that a[index]
will always be a string because of logic in your code, but the problem is that TypeScript doesn’t know that (because the object signature says it can be a string or a number).
To reassure TypeScript, you have at least a couple of choices:
Use a type assertion function:
function assertIsString(value: any): asserts value is string {
if (typeof value !== "string") {
throw new Error(`Expected a string, but got ${typeof value}`);
}
}
Then:
const order: entries[] = data.sort((a, b) => {
const avalue = a[index];
const bvalue = b[index];
assertIsString(avalue);
assertIsString(bvalue);
return avalue.localeCompare(bvalue);
});
This also has the advantage of giving you an explicit error if your code fails to ensure that the property name is only the name of a string property.
Use a type assertion
If you don’t want the (very minimal) overhead of the assertion function, you can just override TypeScript:
const order: entries[] = data.sort((a, b) => (a[index] as string).localeCompare(b[index] as string));
Both
If you know your objects are homogenous, you can combine the two approaches, for instance using the assertion function just on the first entry:
if (data.length > 1) {
assertIsString(data[0][index]);
}
const order: entries[] = data.sort((a, b) => (a[index] as string).localeCompare(b[index] as string));
That way you get a nice explicit error, but you don’t have the overhead of checking during the sort
.
Answered By – T.J. Crowder
This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0