diff --git a/src/compat/index.ts b/src/compat/index.ts index 798b24434..fde5d58a9 100644 --- a/src/compat/index.ts +++ b/src/compat/index.ts @@ -143,6 +143,7 @@ export { merge } from './object/merge.ts'; export { mergeWith } from './object/mergeWith.ts'; export { omit } from './object/omit.ts'; export { pick } from './object/pick.ts'; +export { pickBy } from './object/pickBy.ts'; export { property } from './object/property.ts'; export { propertyOf } from './object/propertyOf.ts'; export { set } from './object/set.ts'; diff --git a/src/compat/object/pickBy.spec.ts b/src/compat/object/pickBy.spec.ts new file mode 100644 index 000000000..8d6a873ee --- /dev/null +++ b/src/compat/object/pickBy.spec.ts @@ -0,0 +1,59 @@ +import { describe, expect, it } from 'vitest'; +import { pickBy } from './pickBy'; + +describe('pickBy', () => { + it('should pick properties based on the predicate function', () => { + const obj = { a: 1, b: 'pick', c: 3 }; + const shouldPick = (value: string | number) => typeof value === 'string'; + const result = pickBy(obj, shouldPick); + expect(result).toEqual({ b: 'pick' }); + }); + + it('should return an empty object if no properties satisfy the predicate', () => { + const obj = { a: 1, b: 2, c: 3 }; + const shouldPick = (value: number) => typeof value === 'string'; + const result = pickBy(obj, shouldPick); + expect(result).toEqual({}); + }); + + it('should return the same object if all properties satisfy the predicate', () => { + const obj = { a: 'pick', b: 'pick', c: 'pick' }; + const shouldPick = (value: string) => typeof value === 'string'; + const result = pickBy(obj, shouldPick); + expect(result).toEqual(obj); + }); + + it('should work with an empty object', () => { + const obj = {}; + const shouldPick = (value: never) => value; + const result = pickBy(obj, shouldPick); + expect(result).toEqual({}); + }); + + it('should work with nested objects', () => { + const obj = { a: 1, b: { nested: 'pick' }, c: 3 }; + const shouldPick = (value: number | { nested: string }, key: string) => key === 'b'; + const result = pickBy(obj, shouldPick); + expect(result).toEqual({ b: { nested: 'pick' } }); + }); + + it('should work with no predicate function', () => { + const obj = { a: 1, b: 'pick', c: 3 }; + const result = pickBy(obj); + expect(result).toEqual(obj); + }); + + it('should return an empty object if the object is null', () => { + const obj = null; + const shouldPick = (value: string) => typeof value === 'string'; + const result = pickBy(obj as unknown as object, shouldPick); + expect(result).toEqual({}); + }); + + it('should return an empty object if the object is undefined', () => { + const obj = undefined; + const shouldPick = (value: string) => typeof value === 'string'; + const result = pickBy(obj as unknown as object, shouldPick); + expect(result).toEqual({}); + }); +}); diff --git a/src/compat/object/pickBy.ts b/src/compat/object/pickBy.ts new file mode 100644 index 000000000..feb75ac44 --- /dev/null +++ b/src/compat/object/pickBy.ts @@ -0,0 +1,43 @@ +/** + * Creates a new object composed of the properties that satisfy the predicate function. + * + * This function takes an object and a predicate function, and returns a new object that + * includes only the properties for which the predicate function returns true. + * + * @template T - The type of object. + * @param {T} obj - The object to pick properties from. + * @param {(value: T[keyof T], key: keyof T) => boolean} shouldPick - A predicate function that determines + * whether a property should be picked. It takes the property's key and value as arguments and returns `true` + * if the property should be picked, and `false` otherwise. + * @returns {Partial} A new object with the properties that satisfy the predicate function. + * + * @example + * const obj = { a: 1, b: 'pick', c: 3 }; + * const shouldPick = (value) => typeof value === 'string'; + * const result = pickBy(obj, shouldPick); + * // result will be { b: 'pick' } + */ +export function pickBy>( + obj: T, + shouldPick?: (value: T[keyof T], key: keyof T) => boolean +): Partial { + if (obj === null || obj === undefined) { + return {}; + } + const result: Partial = {}; + + if (shouldPick === undefined) { + return obj; + } + const keys = Object.keys(obj) as Array; + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + const value = obj[key]; + + if (shouldPick(value, key)) { + result[key] = value; + } + } + + return result; +}