Tomáš Vavřinka
Tomáš Vavřinka

Reputation: 633

Expression of type 'string' can't be used to index type

Sorry for creating another question of this type but even though there are similar ones I am not able to apply theirs solutions to my particular case.

Can someone please help me handle this TypeScript error?

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Record<RouteName, TranslatableRoute>'.
  No index signature with a parameter of type 'string' was found on type 'Record<RouteName, TranslatableRoute>'.(7053)

I am looking for the right way how to solve it not some workaround by destroying type safety. Here is some dummy example of where I hit the problem.

type RouteName = 'home' | 'account'

interface TranslatableRoute {
    cs: string;
    en: string;
}

const translatableRoutes: Record<RouteName, TranslatableRoute> = {
    home: {
        cs: '/',
        en: '/'
    },
    account: {
        cs: '/ucet',
        en: '/account'
    }
}

const findRoute = '/ucet'
const findLang = 'cs'

for (const key in translatableRoutes) {
    if (translatableRoutes[key][findLang] === findRoute) {
        console.log(`Found route\'s name is "${key}"!`)
    }
}

Typescript playground link.

Upvotes: 1

Views: 3922

Answers (1)

Tim Perry
Tim Perry

Reputation: 13216

The problem here is that key is inferred as string rather than keyof typeof translatableRoutes, which would be correct in this case.

There's various complex reasons why that isn't always safe to infer, but the end result is that TypeScript can't give key the right type for you automatically.

In addition, type annotations for for-in loops aren't allowed, so you can't manually fix it inline.

Fortunately though, you can provide a type annotation separately. Replace your for-in loop with:

let key: keyof typeof translatableRoutes;
for (key in translatableRoutes) {
    if (translatableRoutes[key][findLang] === findRoute) {
        console.log(`Found route\'s name is "${key}"!`)
    }
}

That's a little bit more cumbersome, but it gives key the correct type, and ensures that everything later works correctly and safely, with no type casting necessary.

Upvotes: 4

Related Questions