amitdigga
amitdigga

Reputation: 7178

Filter keys of object such that only keys pointing to array are returned (instead of all keys by 'keyof')

For student.ts

type Student = {
    name: string,
    marks: string[],
    subjects: string[]
}

How to get ArrayKey<Student> such that it return only keys which points to any array, here it should point to 'marks'|'subjects'

My try

type ArrayKey<T, Key extends keyof T = keyof T> = T[Key] extends any[] ? Key : never;

let c: ArrayKey<Student> = 'marks';

but it throws error [ts] Type '"marks"' is not assignable to type 'never'

Upvotes: 1

Views: 33

Answers (1)

jcalz
jcalz

Reputation: 330466

You're close, but your code requires the developer to specify Key, which is what you're trying to output. You can instead use mapped types to iterate over the keys of T and then use your conditional type to identify the ones with array-valued properties. Like this:

type ArrayKey<T> = { [Key in keyof T]: T[Key] extends any[] ? Key : never }[keyof T];

type Student = {
  name: string,
  marks: string[],
  subjects: string[]
}

let c: ArrayKey<Student> = 'marks'; // okay

Another way to do it which is closer to your original definition would be to use a distributive conditional type to distribute the conditional over the contituents of K:

type ArrayKey<T, Key extends keyof T = keyof T> = 
   Key extends any ? T[Key] extends any[] ? Key : never : never

That will also work, but K has to be a bare type parameter and Key extends any might be confusing (distributive conditional types are a bit surprising) and it's abusing the default value of K as a hack, so I wouldn't recommend it. Less hacky but still using distributive conditional types:

type ArrayKeyInner<T, Key extends keyof T> =
   Key extends any ? T[Key] extends any[] ? Key : never : never
type ArrayKey<T> = ArrayKeyInner<T, keyof T>

That doesn't abuse a default parameter, which is nice. Still, the distributive conditional type surprise factor still holds so overall I'd still recommend the mapped type solution.


Hope that helps. Good luck!

Upvotes: 3

Related Questions