Home > Software engineering >  How to solve "expression of type 'string' can't be used to index type"
How to solve "expression of type 'string' can't be used to index type"

Time:01-31

I try to migrate a webseite from React to Next.js, but struggeling to implement i18n for SSR-pages. At the moment I try to follow this tutorial here: https://localizely.com/blog/nextjs-i18n-tutorial/

I've already created an lang-folder and put some json-files in there. Here is the content of de.json:

{
    "demo": "Startseite (de)",
    "eventlist":"Event-Liste",
    "menu": {
        "home": "Startseite",
        "events": "Events",
        "nearby" : "In deiner Nähe",
        "worthknowing": "Gut zu wissen",
        "about": "Über uns"
    }
}

I've also followed the tutorial to adapt the _app.tsx:

...
import { useRouter } from 'next/router'
import { IntlProvider } from 'react-intl'
import de from '../lang/de.json'
import en from '../lang/en.json'
import fr from '../lang/fr.json'
import it from '../lang/it.json'
...
const messages = {
  de: de,
  en: en,
  fr: fr,
  it: it,
}
...
function App({ Component, pageProps }: AppProps) {
  let { locale } = useRouter()
  return (
    <IntlProvider locale={locale} messages={messages[locale]}>
      <Layout>
        <Component {...pageProps} />
      </Layout>
    </IntlProvider>
  )
}

export default App

Unfortunately there is a problem to set the messages-prop of the IntlProvider:

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

I can see, what the problem ist, whenI inspect the "messages"-object:

const messages: {
    de: {
        demo: string;
        eventlist: string;
        menu: {
            home: string;
            events: string;
            nearby: string;
            worthknowing: string;
            about: string;
        };
    };
...

As this is the first time, I use TypeScript, i'm some kind of lost to figure out how to solve this situation.

I can think of 3 different solutions:
a) type casting "locale" at the point, where I assign thes "messages"-Prop
b) type casting "locale" at definition time
c) somehow use Strings as object keys in "messages"

What is the best way, to work this out?

CodePudding user response:

The error message is indicating that the type of the locale variable is not matching the keys of the messages object. try to add typeof like so:


let { locale } = useRouter()
const messages = {
  de: de,
  en: en,
  fr: fr,
  it: it,
}
const localeKey = locale as keyof typeof messages //this should help
return (
  <IntlProvider locale={locale} messages={messages[localeKey]}>
    <Layout>
      <Component {...pageProps} />
    </Layout>
  </IntlProvider>
)

but I would advise to look for a better solution for managing language support.

  • Related