user663031
user663031

Reputation:

TypeScript definition for pluck

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

Answers (1)

Aleksey L.
Aleksey L.

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

Related Questions