mirror of
https://github.com/dzeiocom/libs.git
synced 2025-08-06 03:41:59 +00:00
fix: objectClone not correctly cloning a date
Signed-off-by: Avior <f.bouillon@aptatio.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
/// <reference types="jest" />
|
||||
|
||||
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)
|
||||
|
@@ -1,6 +1,11 @@
|
||||
export type BasicObjectKeys = string | number | symbol
|
||||
export type BasicObject<K extends BasicObjectKeys = BasicObjectKeys, V = any> = { [P in K]?: V }
|
||||
|
||||
/**
|
||||
* Pick a from a text union only elements in Keys
|
||||
*/
|
||||
type TextPick<T extends BasicObjectKeys, Keys extends BasicObjectKeys> = T extends Keys ? T : never
|
||||
|
||||
/**
|
||||
* Remap an object to an array through a function
|
||||
*
|
||||
@@ -187,10 +192,24 @@ export function objectClone<T extends BasicObject>(obj: T, options?: { deep?: bo
|
||||
}
|
||||
const clone: Partial<T> = {}
|
||||
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<keyof T, string>] = objectClone(value)
|
||||
return
|
||||
}
|
||||
// special case for Date
|
||||
if (value instanceof Date) {
|
||||
// @ts-expect-error value type is a Date
|
||||
clone[key as Extract<keyof T, Date>] = new Date(value.getTime())
|
||||
return
|
||||
}
|
||||
clone[key as Extract<keyof T, string>] = 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<T extends BasicObject>(obj: T, ...keys: Array<string | number>): T {
|
||||
export function objectOmit<T extends BasicObject, Keys extends (keyof T | (string & {}))>(obj: T, ...keys: Array<Keys | keyof T>): Omit<T, Keys> {
|
||||
const cloned = objectClone(obj, { deep: false })
|
||||
for (const key of keys) {
|
||||
if (key in cloned) {
|
||||
@@ -392,9 +411,9 @@ export function objectGet<T = any>(obj: any, path: Array<string | number | symbo
|
||||
* @param keys the keys to keep
|
||||
* @returns a new copy of `obj` with only `keys` in it
|
||||
*/
|
||||
export function objectPick<V, K extends string | number | symbol>(obj: Record<K, V>, ...keys: Array<K>): Pick<Record<K, V>, K> {
|
||||
export function objectPick<T extends BasicObject, Keys extends (keyof T | (string & {}))>(obj: T, ...keys: Array<Keys | keyof T>): Pick<T, TextPick<Keys, keyof T>> {
|
||||
mustBeObject(obj)
|
||||
return objectFilter(obj, (_, k) => keys.includes(k)) as Pick<Record<K, V>, K>
|
||||
return objectFilter(obj, (_, k) => keys.includes(k)) as Pick<T, Keys>
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user