Simple reproduction of my problem:
const demo = {
aaa: 'aaa',
bbb: 'bbb',
}
const input = 'AAA'
console.log(demo[input.toLowerCase()])
JS itself will work. It will change 'AAA' to 'aaa' which does exist in demo object. But TS throws error:
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ aaa: string; bbb: string; }'.
It's because it sees this value as any String, not 'aaa'. So TS does not allow to any text transformations in it's compiler?
This uppercase value comes from API (graphql enum) so I'm not able to change that. In other hand this object comes from library that uses normal pascalCase keys. So how I can connect both without TS complaying?
CodePudding user response:
What you really want to assert is that input.toLowerCase() results in a valid key for the map demo. You can express that like this:
console.log(demo[input.toLowerCase() as keyof typeof demo])
This should give you full type safety in the surrounding code. This is fine:
let ok: 'aaa' | 'bbb' = demo[input.toLowerCase() as keyof typeof demo]
But these are rejected:
let error1: 'aaa' = demo[input.toLowerCase() as keyof typeof demo]
let error2: 'ccc' = demo[input.toLowerCase() as keyof typeof demo]
CodePudding user response:
In addition to what @Thomas said in the above answer,
Whenever you use Typescript, You should clearly define the types of the variables and objects.
Check out the below code.
type d = {
[key: string]: string
}
const demo: d = {
aaa: 'aaa',
bbb: 'bbb',
}
const input: string = 'AAA'
console.log(demo[input.toLowerCase()])
