Reputation: 1839
Say the array is const items = [{category:'cat1', name:'name1'},{category:'cat2', name:'name2'}]
.
I want to construct the above array to become an object format like the following:
{
'cat1':'name1',
'cat2':'name2'
}
Without typescript, I can do the following to solve the problem:
const parseFunction = (items) => {
const newObj = {};
for (const item of items) {
newObj[item.category] = newObj[item.name];
}
return newObj;
}
However with typescript below:
interface IItems{
category: string,
name: string
}
interface INewObj{
'cat1': string,
'cat2': string
}
const parseFunction = (items: IItems[]) => {
const newObj = {} as INewObj;
for (const item of items) {
newObj[item.category] = newObj[item.name];
}
return newObj;
}
The line newObj[item.category] = newObj[item.name]
throws the following TS error
Element implicitly has an 'any' type because expression of type 'number' can't be used to index type 'IQuotaByCategory'.
No index signature with a parameter of type 'number' was found on type 'IQuotaByCategory'.ts(7053)
How should I fix this?
Upvotes: 0
Views: 2902
Reputation: 3425
Use Record<Keys, Type> to map the unknown keys and values.
Typescript code
const items: IItems[] = [{ category: 'cat1', name: 'name1' }, { category: 'cat2', name: 'name2' }];
interface IItems {
category: string,
name: string
}
type NewObjType = Record<string, string>;
const parseFunction = (items: IItems[]): NewObj => {
const newObj: NewObjType = {};
for (const item of items) {
newObj[item.category] = item.name;
}
return newObj;
}
console.log(parseFunction(items));
Javascript Snippet
"use strict";
const items = [{ category: 'cat1', name: 'name1' }, { category: 'cat2', name: 'name2' }];
const parseFunction = (items) => {
const newObj = {};
for (const item of items) {
newObj[item.category] = item.name;
}
return newObj;
};
console.log(parseFunction(items));
PS: You made a little mistake here newObj[item.category] = newObj[item.name]
since the value does not already exists in the newObj variable. I have changed to the correct assignment as follow: newObj[item.category] = item.name
Upvotes: 1
Reputation: 502
In practice I'm guessing you wouldn't really know that the categories were cat1
, cat2
etc, all you'd know is that they would be strings. Therefore the definition of INewObj
needs to be a little more permissive.
type INewObj = {
[key: string]: string
}
Which can be further shortened to Record<string, string>
.
You could go further and eliminate INewObj
entirely by allowing Typescript to infer it for you:
Upvotes: 1