Skip to content

Commit

Permalink
feat: add pickBy and omitBy
Browse files Browse the repository at this point in the history
  • Loading branch information
yubaoquan committed May 2, 2024
1 parent 069b26c commit 4201f2d
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@ export {
mapKeys,
mapValues,
omit,
omitBy,
pick,
pickBy,
set,
shake,
upperize
Expand Down
30 changes: 30 additions & 0 deletions src/object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,21 @@ export const pick = <T extends object, TKeys extends keyof T>(
}, {} as Pick<T, TKeys>)
}

/**
* Picks properties of an object based on a predicate function.
*
* @param {T} obj - The object from which to pick properties.
* @param {function} predicate - The function used to filter the object's properties.
* @return {object} A new object with properties picked based on the predicate.
*/
export const pickBy = <T extends object, TKeys extends keyof T>(
obj: T,
predicate: (value: T[TKeys]) => boolean = () => true
): Pick<T, TKeys> => {
if (!obj) return {} as Pick<T, TKeys>
return pick(obj, (Object.keys(obj) as TKeys[]).filter(key => predicate(obj[key])))
}

/**
* Omit a list of properties from an object
* returning a new object with the properties
Expand All @@ -205,6 +220,21 @@ export const omit = <T, TKeys extends keyof T>(
)
}

/**
* Omit properties from an object based on a predicate function.
*
* @param {T} obj - The object to omit properties from.
* @param {function} predicate - The function used to determine which properties to omit.
* @return {Omit<T, TKeys>} A new object with properties omitted based on the predicate.
*/
export const omitBy = <T, TKeys extends keyof T>(
obj: T,
predicate: (value: T[TKeys]) => boolean = () => true
): Omit<T, TKeys> => {
if (!obj) return {} as Omit<T, TKeys>
return omit(obj, (Object.keys(obj) as TKeys[]).filter(key => predicate(obj[key])))
}

/**
* Dynamically get a nested value from an array or
* object with a string.
Expand Down
5 changes: 5 additions & 0 deletions src/tests/async.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ import { assert } from 'chai'
import * as _ from '..'
import { AggregateError } from '../async'

// fix error of calling useFakeTimers https://stackoverflow.com/a/77694958/5131623
Object.defineProperty(global, 'performance', {
writable: true,
});

describe('async module', () => {
beforeEach(() => jest.useFakeTimers({ advanceTimers: true }))

Expand Down
43 changes: 43 additions & 0 deletions src/tests/object.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,23 @@ describe('object module', () => {
})
})

describe('pickBy function', () => {
test('handles null input', () => {
const result = _.pickBy(null as unknown as Record<string, unknown>)
assert.deepEqual(result, {})
})

test('handles no identity function', () => {
const result = _.pickBy({ a: 2 })
assert.deepEqual(result, { a: 2 })
})

test('returns picked properties only', () => {
const result = _.pickBy({ a: 1, b: 2, c: 3, d: 4 }, v => v % 2 === 0)
assert.deepEqual(result, { b: 2, d: 4 } as any)
})
})

describe('omit function', () => {
const person = {
name: 'jay',
Expand Down Expand Up @@ -309,6 +326,32 @@ describe('object module', () => {
})
})

describe('omitBy function', () => {
const person = {
name: 'jay',
age: 20,
active: true
}

test('handles null input', () => {
const result = _.omitBy(null)
assert.deepEqual(result, {})
})

test('handles no identity function', () => {
const result = _.omitBy({ a: 2 })
assert.deepEqual(result, {})
})

test('returns object without omitted properties', () => {
const result = _.omitBy(person, v => typeof v === 'string')
assert.deepEqual(result, {
age: 20,
active: true
})
})
})

describe('get function', () => {
type Person = {
name: string
Expand Down

0 comments on commit 4201f2d

Please sign in to comment.