I am trying to use reduce with Typescript to reach a total count of incoming messages. I'm confused on how to add an index signature. I keep getting the error: " Element implicitly has an 'any' type because type '{}' has no index signature." on variables newArray and counts[k]. I have read through several similar questions but have not figured out how to apply them to my specific scenario. I am new to JavaScript and TypeScript.
Here is my array:
var data = [
{ time: '9:54' },
{ time: '9:54' },
{ time: '9:54' },
{ time: '9:55' },
{ time: '9:55' },
{ time: '9:55' },
{ time: '9:55' },
{ time: '9:56' },
{ time: '9:56' },
{ time: '9:56' },
{ time: '9:56' },
{ time: '9:57' },
{ time: '9:57' },
{ time: '9:57' },
{ time: '9:57' },
{ time: '9:57' }
];
This is how I need my array for use in a rechart graph:
var dataWithCounts = [
{ time: '9:54', messages: 3 },
{ time: '9:55', messages: 4 },
{ time: '9:56', messages: 4 },
{ time: '9:57', messages: 5 }
];
With the help of 'Just a Student's' answer from this Stack Overflow question: Group and count values in an array , I have the following.
var counts = data.reduce((newArray, item) => {
let time = item.time;
if (!newArray.hasOwnProperty(time)) {
newArray[time] = 0;
}
newArray[time]++;
return newArray;
}, {});
console.log(counts);
var countsExtended = Object.keys(counts).map(k => {
return { time: k, messages: counts[k] };
});
console.log(countsExtended);
Where and how do I declare an index signature? Below are various things I've tried.
let newArray: { [time: string] };
and receive a duplicate identifier error.
adding string to the parameter var counts = data.reduce((newA:string, item)
gives me an error "Element implicitly has an 'any' type because index expression is not of type 'number'."
adding newA[time].toString()
gives me errors, "The left-hand side of an assignment expression must be a variable or a property access."
The type of your accumulator in the .reduce
call is almost certainly the issue. Since it is just given as {}
, that's what its type is inferred as, and the type {}
doesn't have an index signature. You can fix this by casting your initial value so that it does include a signature:
var counts = data.reduce((newArray, item) => {
let time = item.time;
if (!newArray.hasOwnProperty(time)) {
newArray[time] = 0;
}
newArray[time]++;
return newArray;
}, {} as {[key: string]: any}); // <-- note the cast here
I gave the index signature type any
, but you may want to make it something more specific for your particular case.