Home > other >  How's 'for...in' loop doesn't infer the right type of the 'key' in the
How's 'for...in' loop doesn't infer the right type of the 'key' in the

Time:08-13

I need to modify type of my data from string to number before querying. I am using a loop to modify each value of the data object.

const onSubmit = async (data: { [key in DeclaredInfos]: string }) => {
    const dataFormatted: { [key in DeclaredInfos]: number } | {} = {}
    for (const key in data) {
      dataFormatted[key] = data[key]
    }
  }

got this error, and you see 'key' in recorded to be a string whereas I defined the type 'DeclaredInfos' and so you should be one of these caracters chains

type DeclaredInfos = "action-stocks" | "assets" | "expenses" | "revenues" | "liabilities"
const key: string
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ "action-stocks": string; assets: string; expenses: string; revenues: string; liabilities: string; }'.
  No index signature with a parameter of type 'string' was found on type '{ "action-stocks": string; assets: string; expenses: string; revenues: string; liabilities: string; }'.ts(7053)

please advise something I don't want to use 'any'.

Thanks

CodePudding user response:

One solution would be to use a type assertion


const onSubmit = async (data: { [key in DeclaredInfos]: string }) => {
    const dataFormatted: { [key in DeclaredInfos]: number } | {} = {}
    for (const key in data) {
      dataFormatted[key as DeclaredInfos] = data[key as DeclaredInfos]
    }
  }

CodePudding user response:

Another user has referenced this answer, which you should definitely read. I'm going to address that issue along with a couple others in this answer.

First of all, let's borrow from the linked answer to coerce key into type DeclaredInfos:

let key: DeclaredInfos;
for (key in data) {
  dataFormatted[key] = data[key];
}

You can't give a type annotation to a variable introduced in a for..in loop (again, see the linked answer for details), but this is an acceptable workaround.

Secondly, rather than saying

const dataFormatted: { [key in DeclaredInfos]: number } | {} = {};

You can more succinctly say

const dataFormatted: { [key in DeclaredInfos]?: number } = {};

This indicates that all keys will be of type DeclaredInfos, but also that not necessarily all DeclaredInfos will appear as keys.

Finally, you need to choose between string and number for your value types. You declare data as { [key in DeclaredInfos]: string } and dataFormatted as { [key in DeclaredInfos]?: number } (after the change outlined above). Without an explict transformation from string to number, these don't match.

  • Related