Reputation: 633
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
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