is there a way to describe a kind of "keyfor" in typescript?

62 Views Asked by At

is there any way to express that a key-property for an object should be limited by related value? Something equivalent to keyof but for the value related to given key?

const objectAction = <T extends object>(obj: T): void => obj;
const onlyForObjects = <T extends object>(obj: T, key: keyof T): void =>
  objectAction(obj[key])

should work

onlyForObjects<{ a: number, b: object }>({ a: 0, b: {} }, 'b');

should not work

onlyForObjects<{ a: number, b: object }>({ a: 0, b: {} }, 'a');
2

There are 2 best solutions below

0
On BEST ANSWER

If I understood your question correctly, then following is what you are after:

type ObjKeys<T> = {
  [P in keyof T]: T[P] extends Record<any, any> ? P : never
}[keyof T]

const objectAction = <T>(obj: T): void => console.log(obj)

const onlyForObjects = <T>(obj: T, key: ObjKeys<T>): void => objectAction(obj[key])

onlyForObjects<{ a: number; b: Record<string, unknown> }>({ a: 0, b: {} }, 'b') // compiles
onlyForObjects<{ a: number; b: Record<string, unknown> }>({ a: 0, b: {} }, 'a') // does not compile

12
On

You can do that with a generic Record constraint for type parameter T:

const onlyForObjects = <T extends Record<K, object>, K extends string>(
    obj: T, key: K): void => { }

onlyForObjects({ a: 0, b: {} }, 'b'); // works
onlyForObjects({ a: 0, b: {} }, 'a'); // error

Here is a live code sample.