0

Typescript complains that expression of type 'string' can't be used to index '{ bg: OverridableComponent<SvgIconTypeMap<{}, "svg">>; de: OverridableComponent<SvgIconTypeMap<{}, "svg">>; ... 7 more ...; tr: OverridableComponent<...>; }'

How should we proceed in such a case?

import {
  BulgariaFlag,
  FranceFlag,
  GermanyFlag,
  GreatBritainFlag,
  GreeceFlag,
  ItalyFlag,
  RomaniaFlag,
  RussiaFlag,
  SpainFlag,
  TurkeyFlag,
} from "../Icon";

const flagIcons = {
  bg: BulgariaFlag,
  de: GermanyFlag,
  en: GreatBritainFlag,
  es: SpainFlag,
  fr: FranceFlag,
  gr: GreeceFlag,
  it: ItalyFlag,
  ro: RomaniaFlag,
  ru: RussiaFlag,
  tr: TurkeyFlag,
};

const EmployeeItem: React.FC<{ company: Company; employee: User }> = ({
  company,
  employee,
}) => {
 return 
   <span>
              {employee.spokenLanguages.map((spokenLanguage) => {
                const FlagIcon = flagIcons[spokenLanguage];

                  <FlagIcon
                    key={spokenLanguage}
                    viewBox="0 0 48 48"
                    titleAccess={t(`fields.spokenLanguages.${spokenLanguage}`)}
                  />
              })}
            </span>
};

export default EmployeeItem;

1 Answer 1

2

This means that User.spokenLanguages is array of string whereas it should really be array of "bg" | "de" | ... | "ru" | "tr". You have three solutions

  1. Change User.spokenLanguages to be of type ("bg" | "de" | ... | "ru" | "tr")[] instead of string[]
  2. When rendering, check if language is a valid key of flagIcons using a type guard
const isValidLanguage = (str: string): str is keyof typeof flagIcons => str in flagIcons

{employee.spokenLanguages.map(language => {
  if(!isValidLanguage(language)) return null

  const FlagIcon = flagIcons[language]
  return ...
})}
}
  1. Use const flagIcon: Record<string, ComponentType<TypeOfPropsOfYourIcons> = {...}. Please consider not doing this, as it can cause runtime errors if language is some string that is not in flagIcon.
Sign up to request clarification or add additional context in comments.

1 Comment

Solution 2 is the most flexible and will future-proof your code against having to update the union type proposed by solution 1. For a more strongly typed User interface, you could also make User.spokenLanguages have type (keyof typeof flagIcons)[] but this could pose problems if new languages are added before you have the chance to update flagIcons

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.