I want to create a function which uses a generic type to describe a object and accepts an array of Keys of the generic type. The function returns a function which accepts a object of the generic type and returns a slice only containing the keys passed to the factory function. So the function would look something like this:
function createSlicer<T extends object>(keys: Array<keyof T>) {
return (obj: T) => keys.reduce((acc, key) => ({ ...acc, [key]: obj[key] }), {});
}
The function can be called like this:
interface Person { name: string; age: number; gender: string; }
// (obj: Person) => Pick<Person, 'name'>
const nameSlicer = createSlicer<Person>(['name']);
// (obj: Person) => Pick<Person, 'age'>
const ageSlicer = createSlicer<Person>(['age']);
// (obj: Person) => Pick<Person, 'name' | 'gender'>
const nameAndGenderSlicer = createSlicer<Person>(['name', 'gender']);
Is it possible to get a union of the "keys" variables type that contains the present keys only to define a correct return type for the createSlicer method without using a second generic type?
When the keys are defined as K[]
where K extends keyof T
, it's possible to define the methods return type as Pick<T, K>
:
function createSlicer<T extends object, K extends keyof T>(keys: K[]): (obj: T) => Pick<T, K> {
return (obj: T) => keys.reduce((acc, key) => ({ ...acc, [key]: obj[key] }), {});
}
But this requires to define either none or both generic types, it's not possible to call the function like showed above.