Skip to content

Commit

Permalink
feat(micro-dash): improve the typing of pick()
Browse files Browse the repository at this point in the history
  • Loading branch information
ersimont committed Nov 25, 2020
1 parent 48d267b commit ecedb2e
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 12 deletions.
6 changes: 0 additions & 6 deletions projects/micro-dash/src/lib/object/pick.spec.ts
@@ -1,12 +1,6 @@
import { pick } from './pick';

describe('pick()', () => {
it('fancily narrows types', () => {
let picked: { a: number; b: string };
picked = pick({ a: 1, b: 'b', c: { d: 3 } }, 'a', 'b');
expect(picked).toEqual({ a: 1, b: 'b' });
});

//
// stolen from https://github.com/healthiers/mini-dash
//
Expand Down
12 changes: 6 additions & 6 deletions projects/micro-dash/src/lib/object/pick.ts
@@ -1,4 +1,4 @@
import { Nil } from '../interfaces';
import { IfCouldBe, Nil } from '../interfaces';

/**
* Creates an object composed of the picked `object` properties.
Expand All @@ -10,14 +10,14 @@ import { Nil } from '../interfaces';
* - Lodash: 7,718 bytes
* - Micro-dash: 142 bytes
*/
export function pick<T, K extends keyof T>(
object: T | Nil,
...paths: K[]
): T extends Nil ? {} : Pick<T, K> {
export function pick<T, P extends Array<keyof NonNullable<T>>>(
object: T,
...paths: P
): { [K in P[number]]: NonNullable<T>[K] } | IfCouldBe<T, Nil, {}> {
const result: any = {};
if (object != null) {
for (const path of paths) {
result[path] = object[path];
result[path] = object[path as keyof T];
}
}
return result;
Expand Down
54 changes: 54 additions & 0 deletions projects/micro-dash/src/typing-tests/object/pick.dts-spec.ts
@@ -0,0 +1,54 @@
import { pick } from '../../lib/object';

declare const str: string;
declare const num: number;

declare const obj: {
a: number;
b: Date;
};
// $ExpectType { b: Date; }
pick(obj, 'b');

declare const objOrNull: typeof obj | null;
declare const objOrUndefined: typeof obj | undefined;
declare const objOrNil: typeof obj | null | undefined;
// $ExpectType {} | { b: Date; }
pick(objOrNull, 'b');
// $ExpectType {} | { b: Date; }
pick(objOrUndefined, 'b');
// $ExpectType {} | { b: Date; }
pick(objOrNil, 'b');

declare const indexed: {
[k: string]: number;
[k: number]: number;
};
// $ExpectType { hi: number; }
pick(indexed, 'hi');
// $ExpectType { 5: number; }
pick(indexed, 5);
// $ExpectType { hi: number; 5: number; }
pick(indexed, 'hi', 5);
// $ExpectType { [x: string]: number; }
pick(indexed, str);

declare const record: Record<string, number>;
// $ExpectType { [x: string]: number; }
pick(record, str);

declare const composite: {
[k: number]: Date;
a: 'eh';
b: 'bee';
};
// $ExpectType { a: "eh"; }
pick(composite, 'a');
// $ExpectType { a: "eh"; b: "bee"; }
pick(composite, 'a', 'b');
// $ExpectType { 1: Date; }
pick(composite, 1);
// $ExpectType { [x: number]: Date; }
pick(composite, num);
// $ExpectType { [x: number]: Date; a: "eh"; }
pick(composite, num, 'a');

0 comments on commit ecedb2e

Please sign in to comment.