Okay so I know the title can be a bit confusing, so let me explain.
I have the following interfaces and an array of Items[]
:
interface Items {
step: number;
keyName: string;
value: string;
}
interface ReturnData {
foo: string;
bar: string;
baz: string;
}
const items: Items[] = [
{ step: 1, keyName: 'foo', value: 'fooVal' },
{ step: 2, keyName: 'bar', value: 'barVal' },
{ step: 3, keyName: 'baz', value: 'bazVal' },
];
Now imagine I want function that accepts Items[]
as a parameter, loops over the items
, and for each item assigns a new property with a key of keyName
and a value of value
to a new object of type ReturnData
, and then it finally returns that object as a promise.
For demonstration purposes I am using setInterval
here, but the same would work with a for loop
or other method.
const myFunc = (items: Items[]): Promise<ReturnData> => {
let index = 0;
let returnData: ReturnData = { foo: '', bar: '', baz: '' };
return new Promise(resolve => {
const interval = setInterval(() => {
/*
at index 0: items[index].keyName = 'foo' and items[index].value = 'fooVal'
at index 1: items[index].keyName = 'bar' and items[index].value = 'barVal'
at index 2: items[index].keyName = 'baz' and items[index].value = 'bazVal'
*/
returnData[items[index].keyName] = items[index]?.value;
if (items[index]?.step === items.length) {
clearInterval(interval);
resolve(returnData);
}
else {
index = 1;
}
}, 250);
})
}
(async () => {
const myResult = await myFunc(items);
console.log('myResult value is:', myResult);
/* myResult value is: { foo: 'fooVal', bar: 'barVal', baz: 'bazVal' } */
})();
In plain javascript this function would run properly and return myResult
as expected. But in Typescript I am getting the following error messages when I try to dynamically assign properties to returnData
at each iteration of my setInterval
.
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'ReturnData'.
No index signature with a parameter of type 'string' was found on type 'ReturnData'.ts(7053)
and
Object is possibly 'undefined'.ts(2532)
I have recently started learning Typescript, so my question is, how do I make Typescript understand what is happening here so that it doesn't throw the an error. I know a quick and dirty trick is to assign type any
to my returnData
object to get rid of the errors, but that wouldn't be exactly "type-safe" if that is the correct terminology. What is a better way to go about and make typescript happy?
Full code example at TS Playground
CodePudding user response:
Updating this line should solve your issue:
Issue is that typescript can not associate they keyName of string type as being a key of ReturnData.
interface Items {
step: number;
keyName: keyof ReturnData; // only if you expect that ReturnData keyName will always belong to ReturnData
value: string;
}
typescript or
returnData[(items[index]!.keyName) as keyof ReturnData] = items[index]?.value ?? '';
CodePudding user response:
Just change your interface like this, using keyof
operator.
interface Items {
step: number;
keyName: keyof ReturnData;
value: string;
}
keyName is now: "foo" | "bar" | "baz"