Home > front end >  Problem with proper type inference when accessing object keys
Problem with proper type inference when accessing object keys

Time:10-12

I am trying to write a groupBy generic function in Typescript. I wanted to limit the groupBy fields to keys of specific type for a given object. I am using the solution proposed here and it's working fine limiting the keys I can use. The problem occurs later:

type KeysMatchingType<T, V> = {[K in keyof T]-?: T[K] extends V ? K : never}[keyof T];
type GroupByAllowedType = string | number | boolean 

function groupBy<T extends object>(arr: T[], prop: KeysMatchingType<T,GroupByAllowedType>): Map<GroupByAllowedType, T[]> {
  
  const map: Map<GroupByAllowedType, T[]> = new Map()
  return arr.reduce((acc, current) => {
    const key = current[prop]
    const val = acc.get(key)
    
    if(val){
      val.push(current)
    } else {
      acc.set(key, [current]) 
    }
    return acc
  }, map)
}

at const val = acc.get(key) Typescript is complaining that:

Type 'T[string]' is not assignable to type 'GroupByAllowedType'

even tho the key used to index T is limited by type declaration for the parameter, e.g. prop is such a key that T[prop] should return either boolean, string or number

I am just wondering is this a limitation of Typescript or am I doing something wrong? I guess I could use casting with as, but generally I try to avoid it.

CodePudding user response:

Change the constraint from object to this:

function groupBy<T extends Record<KeysMatchingType<T, GroupByAllowedType>, GroupByAllowedType>>(arr: T[], prop: KeysMatchingType<T, GroupByAllowedType>): Map<GroupByAllowedType, T[]> {

Similarly to this answer from a while ago, you're able to tell TypeScript that you only care about the keys of T that correspond to GroupByAllowedType simply by using a recursive constraint.

Then as you see here, this one change fixes the error :)

  • Related