How to infer type of interface property by passing its property as argument?

here is my example:

export const getField = <T extends Record<string, any>, K extends keyof T = keyof T>(fieldName: K) => {
  const record = injectRecord<T>(); // sideEffect

  return { field: record[fieldName] };
};

// in real life here will be different objects
const injectRecord = <T>() => ({ number: 123, bool: true, string: 'asd' } as T); 

// typeof field = string | number | boolean
const { field } = getField<{ number: number; string: string; bool: boolean }>('bool');

I want to get the correct type by passing the interface key, for the example above field should be exactly Boolean

>Solution :

You can achieve this with a curried function:

const injectRecord = <T>(): T => ({ n: 123, s: 'abc', b: true } as T);

const getField = <T extends Record<string, unknown>>() => <K extends keyof T>(key: K): { field: T[K] } => {
    const record = injectRecord<T>();
    return { field: record[key] };
}

const { field } = getField<{ n: number; s: string; b: boolean }>()('b');
//       ^? const field: boolean

See TypeScript Playground. Prompted by this comment

Leave a Reply