0
votes

I'm using react and typescript and am getting this error on the last line of the code block below.

Element implicitly has an 'any' type because expression of type 'number' can't be used to index type '{}'. No index signature with a parameter of type 'number' was found on type '{}'. ts(7053)

from the line hemisphereInfo[hemisphere][country] = countryInfo; (see below for full code). It has an issue with the [country] bit.

Basically, I'm trying to add an unknown key pair to an object that's typed with an interface.

export interface IHemisphere {
  [key: string]: object
  north: {
    [key: string]: object
  }; 
  south: {
   [key: string]: object
  };
}    

const hemisphereInfo: IHemisphere = {
  north: {},
  south: {},
};

for (const hemisphere in hemisphereInfo) {
const countriesInHemisphere: string[] = this.hemiAPI(hemisphere) as unknown as string[];
  
  for (const country in countriesInHemisphere) {
    const countryInfo = this.countryAPI(country);
    hemisphereInfo[hemisphere][country] = countryInfo;
  }
}

Firstly, country is a string, not a number like it says in the error message. Secondly, I've seen examples solving this problem with strongly typed keys, but I won't know what they keys will be when they come in, so I can't specify each one in the interface.

1
as unknown as string[] that's like ejecting from type safety. Ideally, this.hemiAPI would be typed properly so that TypeScript can tell which type is returned correctly.Emile Bergeron
countriesInHemisphere is an array, so for(key in arr) will return numbers for key.Emile Bergeron
Does this answer your question? Loop through an array in JavaScriptEmile Bergeron

1 Answers

0
votes

There are a bunch issues going on here.

1) Difference Between of and in

When looping through an array, using the syntax x of array gives you the keys, while x in array gives you the values. To avoid confusion, it may be better to use a specialized function like array.forEach().

2) All keys are type string

When dealing with array keys which are numbers, typescript sees them as string. When dealing with the keys of an IHemisphere typescript still gives us string instead of the literals 'north' and 'south'.

3) Vague index signature

The type for the keys north and south in IHemisphere is an object with string keys and object values. But they type for unknown keys as described by your index signature is just object.

Solution

Here is one possible solution. I switched country in to country of to address #1, added the assertion hemisphere as keyof IHemisphere to fix #2, and removed the top-level index signature from IHemisphere to fix #3.

export interface IHemisphere {
  north: {
    [key: string]: object
  }; 
  south: {
   [key: string]: object
  };
}    

const hemisphereInfo: IHemisphere = {
  north: {},
  south: {},
};

for (const hemisphere in hemisphereInfo) {
const countriesInHemisphere: string[] = this.hemiAPI(hemisphere) as unknown as string[];
  
  for (const country of countriesInHemisphere) {
    const countryInfo = this.countryAPI(country);
    hemisphereInfo[hemisphere as keyof IHemisphere][country] = countryInfo;
  }
}