Reputation: 7609
I have an angular table where each row can contain sub cells
I defined the following interface
export interface TableCell {
[key: string]: string | number
}
export interface TableRow {
[key: string]: string | number | TableCell
}
I try to make a sorting function, where I use key and the nested key to filter elements like this
private sort({ column, direction, subColumn }: TableSortEvent) {
if (direction === '' || column === '') {
return [...this.rows]
} else {
return [...this.rows].sort((a, b) => {
const colA = a[column]
const colB = b[column]
if (
(typeof colA === 'string' || typeof colA === 'number') &&
(typeof colB === 'string' || typeof colB === 'number')
) {
const res = this.compare(colA, colB)
return direction === 'asc' ? res : -res
}
if (subColumn) {
const subColA = colA[subColumn]
const subColB = colB[subColumn]
if (
(typeof subColA === 'string' || typeof subColA === 'number') &&
(typeof subColB === 'string' || typeof subColB === 'number')
) {
const res = this.compare(subColA, subColB)
return direction === 'asc' ? res : -res
}
}
return 0
})
}
}
So if a[column]
is a string or number, I sort it, else I check the subKey.
It work nice but at build time I have the following
No index signature with a parameter of type 'string' was found on type 'string | number | TableCell'. const subColB = colB[subColumn]
How can I fix this ?
export interface TableSortEvent {
column: string
subColumn?: string
direction: TableSortDirection
}
Upvotes: 0
Views: 1279
Reputation: 1074335
Your objects don't have an index signature, so you can't just index into them with a string, it's not type-safe.
To handle that, you can use the keyof
type operator, which lets you say that column
is a valid key for the type of object you're sorting (and subColumn
is a valid key for the subordinate object).
Without seeing more of your code it's hard to give you updated code, but for instance here's an example where we sort an object array by either a string or number property:
interface Foo {
strCol: string;
numCol: number;
}
const x: Foo[] = [
{ strCol: "1", numCol: 1 },
{ strCol: "2", numCol: 2 },
{ strCol: "3", numCol: 3 },
{ strCol: "4", numCol: 4 },
];
function sortBy(a: Foo[], col: keyof Foo) {
a.sort((a, b) => {
// Get the values from the objects as constants
// Their type starts out as `string | number`.
const avalue = a[col];
const bvalue = b[col];
if (typeof avalue === "string") {
// Here, `avalue` is narrowed to `string`, and we can
// safely assert that `bvalue` is `string` as well
return avalue.localeCompare(bvalue as string);
}
// Here, `avalue` is narrowed to `number`, and we can
// safely assert that `bvalue` is `number` as well
return avalue - (bvalue as number);
});
}
Upvotes: 2