Reputation:
The TypeScript documentation gives the following example for defining a pluck
function, using "index types" (slightly modified):
function pluck<T, K extends keyof T>(o: T, name: K): T[K] {
return o[name];
}
which is obviously called as
pluck({a: 1}, 'a')
However, I want to define a pluck
which takes just a property name, and yields a function I can apply to an object to obtain that property, as in
const getA = pluck('a');
getA({a: 1})
I tried the following:
function pluck<T, K extends keyof T>(p: K) {
return function(o: T): T[K] {
return o[p];
};
}
This compiles fine, but when I try to use it:
const a = {a: 1};
const getA = pluck('a');
console.log(getA(a));
I get the error
Argument of type '"a"' is not assignable to parameter of type 'never'. [2345]
on the line where I call pluck('a')
. Is there any way to do what I want?
Upvotes: 5
Views: 4870
Reputation: 37948
You can achieve this by moving T
type definition into inner function and defining constraint for it:
function pluck<KeyType extends string>(p: KeyType) {
return function <T extends Record<KeyType, any>>(o: T): T[KeyType] {
return o[p];
};
}
const getA = pluck('a');
const a = { a: 1 };
console.log(getA(a));
const b = { b: 1 };
console.log(getA(b)); //error
Upvotes: 4