Typescript Error: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type

Trying to get some data for a modal based on a feature name. The feature itself is a string coming from an API. The messages object is for translating the strings in other countries.

import { defineMessages } from 'react-intl';

messages = defineMessages({
  userLimitsHeading: {
    defaultMessage: 'User limits',
  },
  userLimitsSubheading: {
    defaultMessage: 'Get the flexibility to grow your team beyond 10 users.',
  },
  agentLimitHeading: {
    defaultMessage: 'Agent limits',
  },
  agentLimitSubheading: {
    defaultMessage: 'Get the flexibility to grow your team beyond 3 agents.',
  },
});

interface ModernizedPlanSelectionModalTypes {
  feature: string;
}

const getData = (feature) => {
  const heading = messages[`${feature}Heading`];
  const subHeading = messages[`${feature}Subheading`];
  return {
    heading,
    subHeading,
  };
}

I'm getting 2 typescript errors in the getData function, specifically in the bit where I grab the message with the concatenated string key:

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'userLimitsHeading: { id: string; description: string; defaultMessage: string; }; userLimitsSubheading: { id: string; description: string; defaultMessage: string; }; ... //Continues on for the rest of them
No index signature with a parameter of type 'string' was found on type ' userLimitsHeading: { id: string; description: string; defaultMessage: string; }; userLimitsSubheading: { id: string; description: string; defaultMessage: string; }; //Continues on for the rest of them'

Upvotes: 1

Views: 1577

Answers (1)

g2jose
g2jose

Reputation: 1465

You need to add an explicit type assertion to get around this like so:

const getData = (feature: string) => {
  const heading = messages[`${feature}Heading` as keyof typeof messages]
  const subHeading = messages[`${feature}Subheading` as keyof typeof messages]
  return {
    heading,
    subHeading,
  }
}

The root of the issue is that the keys in the messages variable is typed as

'userLimitsHeading' | 'userLimitsSubheading' | 'agentLimitHeading' | 'agentLimitSubheading'

which is a narrow subset of string.

${feature}Heading however is typed to string - the error message is telling you that you cannot use just any string to reference keys in the object.

Typescript 4.1 however adds support for template literal types, so this may no longer be required if you're able to upgrade your environment to use this.

See also https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html

Upvotes: 4

Related Questions