Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

170
Views
is it possible to use value of some key as new key in typescript?

say i have an object list, and each object is type of IUser

type IUser = {
 id: string
 name: string
 ...
}

I want to convert this list to a map, use id as key(or other property from object).

And hope I can have an accurate typescript description for this type, so that I can use it like this const idMap :IMapKeyedByK<IUser, 'id'> = {...}

type IMapKeyedByK<T, K> = {
  [key: T[K]]: T
}

How can I implement IMapKeyedByK<T, K>?

about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

Note that JavaScript object index types are always strings or symbols. You can index an object using numbers, but they get converted to strings: ({42: 'foo'})['42'] == 'foo'. So unless your IUser contains symbols, this is not very useful because you might as well hardcode string keys.

That said, you can do it. We have to constrain K to be a valid key type, and constrain T so that it contains a key of type K with a value that can also be used as a key.

type ObjectKey = string | number | symbol
type IMapKeyedByK<T extends Record<K, ObjectKey>, K extends ObjectKey> = Record<T[K], T>

const idMap: IMapKeyedByK<IUser, 'id'> = {}
idMap['zaphod'] = {id: 'zaphod', name: 'Zaphod Beeblebrox'} // OK
idMap[Symbol()] = {id: 'zaphod', name: 'Zaphod Beeblebrox'} // Error! Type 'symbol' cannot be used as an index type.
about 4 years ago · Juan Pablo Isaza Report

0

A correct type here is:

type IMapKeyedByK<T, K extends keyof T> = T[K] extends PropertyKey // if the property value can be used as key
    ? Record<T[K], T>  // record indexed by the property value
    : never;   

It will ensure that you pass a key belonging to T and also that the value for that key is valid to use as an object key.

Example:

type IUser = {
 id: string
 name: string
 age: number
 department: {
     departmentName: string
 }
}

type IMapKeyedByK<T, K extends keyof T> = T[K] extends PropertyKey ? Record<T[K], T> : never;

type MapById   = IMapKeyedByK<IUser, "id">;   //works - indexed by string
type MapByName = IMapKeyedByK<IUser, "name">; //works - indexed by string
type MapByAge  = IMapKeyedByK<IUser, "age">;  //works - indexed by number

type MapByDepartment = IMapKeyedByK<IUser, "department">; //produces `never` because cannot be indexed by object
type MapByPhone = IMapKeyedByK<IUser, "phone">;           //error - "phone" does not exist

Playground Link

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!