pa1nd
pa1nd

Reputation: 432

Access Object using Index in .find() in Typescript

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

Answers (1)

zerkms
zerkms

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

Related Questions