I thought this error was strange to see, since intuitively you would expect number
and Record<A, number>[A]
to be compatible, and therefore also (B & Record<A, number>)[A]
. I'm not sure what causes this, so it's hard to make a more minimal example. But I'll include some more context below:
This error appeared when I was making a function for aggregating table data, summing over specific columns. The table data is an array of objects, all with the same keys, although these keys are all unknown at compile time.
However, the table data is split into columns that are to be summed, and columns that are to be constant. So the row needs to be typed as a union of Record
s.
I was wanting to type this function generically so that it would work on arbitrary data, and also to have as arguments which columns to group by and which to sum over, also working as a filter. Here's a fairly minimal example that causes the same error:
//type P = 'a' | 'b' | 'c';
//type S = 'x' | 'y' | 'z';
//const aggregateRows = (
type RecordKeys = string | number | symbol;
const aggregateRows = <P extends RecordKeys, S extends RecordKeys>(
otherCols: P[],
numberCols: S[],
rows: (Record<P, unknown> & Record<S, number>)[],
): void => {
rows[0][numberCols[0]] = 1; // <--- ERROR in question
}
Somewhat oddly, when I tried to simplify by avoiding generics, defining P
and S
outside the function to be non-overlapping string literals, the error just went away (see the commented out lines). Am I doing something wrong?
Any help would be appreciated.
CodePudding user response:
I did find a way to get the error to go away:
rows[0][numberCols[0]] = (
rows[0][numberCols[0]] 1 as (Record<P, unknown> & Record<S, number>)[S]
);
However, I'm pretty sure this is caused by an error in my typing, making typescript too strict in what it will accept as the contents of the rows
object. I think that should be fixed instead, rather than working my way around the error, but I don't know what I'm doing wrong.
CodePudding user response:
you can try the following, hope that helps
type RecordKeys = string | number | symbol;
const aggregateRows = <P extends RecordKeys, S extends RecordKeys>(
otherCols: P[],
numberCols: S[],
rows: Record<P, unknown | number>[],
): void => {
(rows[0] as any)[numberCols[0]] = 1;
}