Reputation: 432
I am trying to access an object using index notation in typescript. But I cannot find a way that keeps my types (without using any).
In typescript I get the following error (strict mode):
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ givenName: string; familyName: string; email: string; active: boolean; }'.
No index signature with a parameter of type 'string' was found on type '{ givenName: string; familyName: string; email: string; active: boolean; }'.
// Example document
interface user {
givenName: string
familyName: string
email: string
active: boolean
}
const user:user = {
givenName: 'Max',
familyName: 'Maier',
email: '[email protected]',
active: true,
}
// To be used like this
const match = ['givenName', 'familyName', 'email'].find(e =>
!!user[e] && user[e].toLowerCase().includes('searchQuery')
)
there are no errors when using a static string.
!!user['givenName'] && user['givenName'].toLowerCase().includes('searchQuery')
Defining an indexer seems to always throw me into the problem of loosing type safety. E.g.
[index: string]: string | boolean | undefined
will give an error with the .toLowerCase()
. I could fix it using any
but that is not what I want.
In my opinion the best solution would be to make typescript understand that e
is an existing index with something like this:
['givenName', 'familyName', 'email'].find((e:'givenName'| 'familyName'| 'email' ) =>
But I failed getting the error:
Type 'string' is not assignable to type '"givenName" | "familyName" | "email"'
I'm able to hack it using any but I can't figure out type safe way to solve this.
Upvotes: 0
Views: 78
Reputation: 254896
Do it this way
const match = (['givenName', 'familyName', 'email'] as const).find(e =>
!!user[e] && user[e].toLowerCase().includes('searchQuery')
)
Then the array is typed as an array of union of literals, not just as a string[]
and the e
is properly typed as a union of literals correspondingly.
References:
Upvotes: 1