Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Write a typesafe 'pick' function in typescript

lodash has the pick function which is used as follows:

var object = { 'a': 1, 'b': '2', 'c': 3 };

_.pick(object, ['a', 'c']);
// => { 'a': 1, 'c': 3 }

I would like to write a type-safe version of this in typescript.

Usage of this function should be

pick(object, o => o.a, o.b)

The goal is not to specify the same keys twice, and at the same time conserve type safety.

Is this possible to achieve?

like image 427
rony l Avatar asked Nov 10 '17 23:11

rony l


4 Answers

Sounds like you might be looking for the Pick type. Would something like this work for you?

function pick<T, K extends keyof T>(obj: T, ...keys: K[]): Pick<T, K> {
  const ret: any = {};
  keys.forEach(key => {
    ret[key] = obj[key];
  })
  return ret;
}

const o = {a: 1, b: '2', c: 3}
const picked = pick(o, 'b', 'c');

picked.a; // not allowed
picked.b  // string
picked.c  // number
like image 199
ethan.roday Avatar answered Oct 23 '22 06:10

ethan.roday


With Object.fromEntries (es2019):

function pick<T extends object, K extends keyof T> (base: T, ...keys: K[]): Pick<T, K> {
  const entries = keys.map(key => ([key, base[key]]));
  return Object.fromEntries(entries);
}
like image 40
Seb D. Avatar answered Oct 23 '22 06:10

Seb D.


here's mine, using Object.assign()

function pick<T, K extends keyof T>(object: T, keys: K[]): Pick<T, K> {
  return Object.assign(
    {},
    ...keys.map(key => {
      if (object && Object.prototype.hasOwnProperty.call(object, key)) {
        return { [key]: object[key] };
      }
    })
  );
};
like image 3
bayu Avatar answered Oct 23 '22 07:10

bayu


The lodash type definitions use Pick to propagate the props, so you don't have to define it manually. Just install them with npm i --save-dev @types/lodash or yarn add -D @types/lodash.

like image 1
Petr Bela Avatar answered Oct 23 '22 06:10

Petr Bela