Skip to content

Commit

Permalink
feat(accessors): add pick function
Browse files Browse the repository at this point in the history
This function is a tighter version of lodash's `pick` function that enables proper typing
  • Loading branch information
cahilfoley committed May 26, 2019
1 parent 8eb0efc commit ad55229
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/accessors/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { default as clone } from './clone'
export { default as get } from './get'
export { default as pick } from './pick'
export { default as set } from './set'
37 changes: 37 additions & 0 deletions src/accessors/pick.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import pick from './pick'

describe('Pick Properties (pick)', () => {
it('should exclude all properties that were not specified', () => {
const testObject = { foo: 'hello', bar: 'world', baz: [1, 2, 3], some: 'property' }
const pickedObject = pick(testObject, 'foo', 'bar')

expect(pickedObject).toEqual({ foo: 'hello', bar: 'world' })
})

it('should return an empty object when `object` is nullish', () => {
const testObjectNull = null as {}
const pickedObjectNull = pick(testObjectNull)

expect(pickedObjectNull).toEqual({})

let testObjectUndefined: {}
const pickedObjectUndefined = pick(testObjectUndefined)
expect(pickedObjectUndefined).toEqual({})
})

describe('Overloaded signatures', () => {
it('should accept an array of strings as keys', () => {
const testObject = { foo: 'hello', bar: 'world', baz: [1, 2, 3], some: 'property' }
const pickedObject = pick(testObject, ['foo', 'bar', 'baz'])

expect(pickedObject).toEqual({ foo: 'hello', bar: 'world', baz: [1, 2, 3] })
})

it('should accept any number of string arguments as keys', () => {
const testObject = { foo: 'hello', bar: 'world', baz: [1, 2, 3], some: 'property' }
const pickedObject = pick(testObject, 'foo', 'bar', 'baz')

expect(pickedObject).toEqual({ foo: 'hello', bar: 'world', baz: [1, 2, 3] })
})
})
})
41 changes: 41 additions & 0 deletions src/accessors/pick.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import flatten from '../array/flatten'

/**
*
* Creates a new object containing only the properties of `object` that are specified in `keys`.
*
* @param object The base object that properties will be picked from
* @param keys The keys to pick
*
* @example
* const original = { foo: 'hello', bar: 'world', baz: false, something: [1, 2, 3] }
* const picked = pick(original, 'foo', 'something')
*
* console.log(picked) // { foo: 'hello', something: [1, 2, 3] }
* console.log(Object.keys(picked)) // ['foo', 'something']
*
*/
export default function pick<T extends Record<string, any>, U extends keyof T>(
object: T,
...keys: U[]
): Pick<T, U>
export default function pick<T extends Record<string, any>, U extends keyof T>(
object: T,
keys: U[],
): Pick<T, U>
export default function pick<T extends Record<string, any>, U extends keyof T>(
object: T,
...keys: U[] | [U[]]
): Pick<T, U> {
const resolvedKeys = flatten(keys)

const output = resolvedKeys.reduce(
(output, key) => {
output[key] = object[key]
return output
},
{} as T,
)

return output as Pick<T, U>
}

0 comments on commit ad55229

Please sign in to comment.