diff --git a/packages/object-util/__tests__/index.test.ts b/packages/object-util/__tests__/index.test.ts
index beb05fa..1f91938 100644
--- a/packages/object-util/__tests__/index.test.ts
+++ b/packages/object-util/__tests__/index.test.ts
@@ -1,5 +1,6 @@
///
+import { objectPick } from '../dist/ObjectUtil'
import { isObject, objectClean, objectClone, objectEqual, objectFind, objectGet, objectKeys, objectLoop, objectMap, objectOmit, objectRemap, objectSet, objectSize, objectSort, objectValues } from '../src/ObjectUtil'
describe('Throw if parameter is not an object', () => {
@@ -220,6 +221,25 @@ describe('Object Clone Tests', () => {
expect(clone).not.toEqual(obj)
})
+ it('it should clone dates', () => {
+ const date = new Date('2025-01-02')
+ const obj = {
+ pouet: date,
+ }
+
+ // check base clone
+ const clone = objectClone(obj)
+ expect(clone).toEqual(obj)
+
+ // check that it is deep (date changes doesn't affect the clone)
+ date.setFullYear(2020)
+ expect(clone).not.toEqual(obj)
+
+ // check a value change doesn't affect the clone
+ clone.pouet = new Date()
+ expect(clone).not.toEqual(obj)
+ })
+
it('should deeply clone the object when option is set', () => {
const obj = {
pouet: {is: 'first'},
@@ -416,6 +436,28 @@ describe('Object Omit Tests', () => {
})
})
+describe('Object Pick Tests', () => {
+ it('should pick certain elements', () => {
+ const obj = {a: 'a', b: 'c', c: 'b'}
+ expect(objectPick(obj, 'b')).toEqual({b: 'c'})
+ })
+
+ it('should not care when key to pick is not present', () => {
+ const obj = {a: 'a', b: 'c', c: 'b'}
+ expect(objectPick(obj, 'b', 'd')).toEqual({b: 'c'})
+ })
+
+ it('should work with Object.freeze', () => {
+ const obj = {a: 'a', b: 'c', c: 'b'}
+ expect(objectPick(Object.freeze(obj), 'b', 'd')).toEqual({b: 'c'})
+ })
+
+ it('should work with an array', () => {
+ const obj = [1, 2, 3, 4]
+ expect(objectPick(obj, 1, 3)).toEqual([undefined,2,undefined,4])
+ })
+})
+
describe('Is Object Tests', () => {
it('null is not an "object"', () => {
expect(isObject(null)).toBe(false)
diff --git a/packages/object-util/src/ObjectUtil.ts b/packages/object-util/src/ObjectUtil.ts
index bacb245..c828f96 100644
--- a/packages/object-util/src/ObjectUtil.ts
+++ b/packages/object-util/src/ObjectUtil.ts
@@ -1,6 +1,11 @@
export type BasicObjectKeys = string | number | symbol
export type BasicObject = { [P in K]?: V }
+/**
+ * Pick a from a text union only elements in Keys
+ */
+type TextPick = T extends Keys ? T : never
+
/**
* Remap an object to an array through a function
*
@@ -187,10 +192,24 @@ export function objectClone(obj: T, options?: { deep?: bo
}
const clone: Partial = {}
objectLoop(obj, (value, key) => {
- if (typeof value === 'object' && value != null && (typeof options?.deep === 'undefined' || options.deep)) {
+ if (
+ typeof value === 'object' // make sure child is an object
+ && value != null // object is not null
+ && (
+ typeof options?.deep === 'undefined'
+ || options.deep
+ ) // deep is set to true or undefined
+ && !(value instanceof Date) // object is not a date
+ ) {
clone[key as Extract] = objectClone(value)
return
}
+ // special case for Date
+ if (value instanceof Date) {
+ // @ts-expect-error value type is a Date
+ clone[key as Extract] = new Date(value.getTime())
+ return
+ }
clone[key as Extract] = value
})
return clone as T
@@ -302,7 +321,7 @@ export function objectClean(obj: BasicObject, options?: { cleanUndefined?: boole
* @param keys the keys to emit
* @returns the cloned object
*/
-export function objectOmit(obj: T, ...keys: Array): T {
+export function objectOmit(obj: T, ...keys: Array): Omit {
const cloned = objectClone(obj, { deep: false })
for (const key of keys) {
if (key in cloned) {
@@ -392,9 +411,9 @@ export function objectGet(obj: any, path: Array(obj: Record, ...keys: Array): Pick, K> {
+export function objectPick(obj: T, ...keys: Array): Pick> {
mustBeObject(obj)
- return objectFilter(obj, (_, k) => keys.includes(k)) as Pick, K>
+ return objectFilter(obj, (_, k) => keys.includes(k)) as Pick
}
/**