diff --git a/packages/object-util/__tests__/index.test.ts b/packages/object-util/__tests__/index.test.ts
index e2f3f5b..3a24165 100644
--- a/packages/object-util/__tests__/index.test.ts
+++ b/packages/object-util/__tests__/index.test.ts
@@ -1,6 +1,13 @@
///
-import { objectSize, objectMap, objectSort, objectEqual, objectKeys, objectSet, objectLoop, objectClone, objectValues } from '../src/ObjectUtil'
+import { objectSize, objectMap, objectSort, objectEqual, objectKeys, objectSet, objectLoop, objectClone, objectValues, objectClean, isObject } from '../src/ObjectUtil'
+
+describe('Throw if parameter is not an object', () => {
+ it('should works', () => {
+ // @ts-ignore
+ expect(objectKeys).toThrow()
+ })
+})
describe('Object Map tests', () => {
it('should works', () => {
@@ -136,32 +143,20 @@ describe('Object Clone Tests', () => {
expect(clone).not.toEqual(obj)
})
- it('Should keep types', () => {
- const obj = {
- a: [],
- b: '10',
- c: 10,
- d: {},
- e: [10],
- f: {g: 10}
- }
+ it('should clone an Array', () => {
+ const obj = ['one', 'two']
const clone = objectClone(obj)
expect(clone).toEqual(obj)
+ clone[0] = 'three'
+ expect(clone).not.toEqual(obj)
})
- it ('Should clone any types', () => {
- const obj = {
- a: [],
- b: '10',
- c: 10,
- d: {},
- e: [10],
- f: {g: 10}
- }
- objectLoop(obj, (subObj) => {
- const clone = objectClone(subObj)
- expect(clone).toEqual(subObj)
- })
+ it('should deeply clone an Array', () => {
+ const obj = ['one', 'two', ['three']]
+ const clone = objectClone(obj)
+ expect(clone).toEqual(obj)
+ ;(clone[2][0] as string) = 'zero'
+ expect(clone).not.toEqual(obj)
})
})
@@ -236,3 +231,46 @@ describe('Object Equal Test', () => {
})).toBe(true)
})
})
+
+describe('Object Clean Tests', () => {
+ it('should clean undefined by default', () => {
+ const obj = {a: '', b: null, c: undefined}
+ objectClean(obj)
+ expect(obj).toEqual({a: '', b: null})
+
+ const obj2 = {a: '', b: null, c: undefined}
+ objectClean(obj2, {cleanUndefined: false})
+ expect(obj2).toEqual({a: '', b: null, c: undefined})
+ })
+ it('should clean null when set', () => {
+ const obj = {a: '', b: null, c: undefined}
+ objectClean(obj, {cleanNull: true})
+ expect(obj).toEqual({a: ''})
+ })
+ it('should clean deep by default', () => {
+ const obj = {a: '', b: null, c: undefined, d: {da: '', db: null, dc: undefined}}
+ objectClean(obj)
+ expect(obj).toEqual({a: '', b: null, d: {da: '', db: null}})
+ })
+})
+
+describe('Is Object Tests', () => {
+ it('null is not an "object"', () => {
+ expect(isObject(null)).toBe(false)
+ })
+ it('boolean is not an "object"', () => {
+ expect(isObject(true)).toBe(false)
+ })
+ it('undefined is not an "object"', () => {
+ expect(isObject(undefined)).toBe(false)
+ })
+ it('string is not an "object"', () => {
+ expect(isObject("null")).toBe(false)
+ })
+ it('number is not an "object"', () => {
+ expect(isObject(0)).toBe(false)
+ })
+ it('object is an "object"', () => {
+ expect(isObject({})).toBe(true)
+ })
+})
diff --git a/packages/object-util/src/ObjectUtil.ts b/packages/object-util/src/ObjectUtil.ts
index cda57a3..3501161 100644
--- a/packages/object-util/src/ObjectUtil.ts
+++ b/packages/object-util/src/ObjectUtil.ts
@@ -9,6 +9,7 @@ export function objectMap(
obj: Record,
fn: (value: T, key: string, index: number) => J
): Array {
+ mustBeObject(obj)
const list: Array = []
objectLoop(obj, (item, key, index) => {
list.push(fn(item, key, index))
@@ -25,6 +26,7 @@ export function objectLoop(
obj: Record,
fn: (value: T, key: string, index: number) => boolean | void
): boolean {
+ mustBeObject(obj)
const keys = objectKeys(obj)
for (let index = 0; index < keys.length; index++) {
const key = keys[index]
@@ -41,6 +43,7 @@ export function objectLoop(
* @param obj the object to transform
*/
export function objectValues(obj: Record): Array {
+ mustBeObject(obj)
return Object.values(obj)
}
@@ -48,6 +51,7 @@ export function objectValues(obj: Record): Array {
* @deprecated use `objectValues`
*/
export function objectToArray(obj: Record): Array {
+ mustBeObject(obj)
return objectValues(obj)
}
@@ -56,6 +60,7 @@ export function objectToArray(obj: Record): Array {
* @param obj the object
*/
export function objectKeys(obj: Record): Array {
+ mustBeObject(obj)
return Object.keys(obj)
}
@@ -64,6 +69,7 @@ export function objectKeys(obj: Record): Array {
* @param obj the object
*/
export function objectSize(obj: Record): number {
+ mustBeObject(obj)
return objectKeys(obj).length
}
@@ -78,6 +84,7 @@ export function objectSort = Record>(
obj: T,
fn?: Array | ((a: keyof T, b: keyof T) => number)
): T {
+ mustBeObject(obj)
const ordered: any = {}
let sortedKeys: Array = []
if (Array.isArray(fn)) {
@@ -95,6 +102,7 @@ export function objectSort = Record>(
* @deprecated use `objectClone`
*/
export function cloneObject>(obj: T): T {
+ mustBeObject(obj)
return objectClone(obj)
}
@@ -103,14 +111,15 @@ export function cloneObject>(obj: T): T {
* @param obj the object to clone
*/
export function objectClone>(obj: T): T {
- if (typeof obj !== 'object') {
- const v = obj
- return v
- }
+ mustBeObject(obj)
if (Array.isArray(obj)) {
const arr: Array = []
for (const item of obj) {
- arr.push(objectClone(item))
+ if (isObject(item)) {
+ arr.push(objectClone(item))
+ } else {
+ arr.push(item)
+ }
}
return arr as unknown as T
}
@@ -136,6 +145,7 @@ export function objectClone>(obj: T): T {
* @param value the value
*/
export function objectSet(obj: Record, path: Array, value: any): void {
+ mustBeObject(obj)
let pointer = obj
for (let index = 0; index < path.length; index++) {
const key = path[index]
@@ -167,6 +177,8 @@ export function objectSet(obj: Record, path: Array
* @param y the second object
*/
export function objectEqual(x: Record, y: Record): boolean {
+ mustBeObject(x)
+ mustBeObject(y)
if (objectSize(x) !== objectSize(y)) {
return false
}
@@ -186,6 +198,40 @@ export function objectEqual(x: Record, y: Record): boo
return res
}
+/**
+ * deeply compare objects and return if they are equal or not
+ * @param x the first object
+ * @param y the second object
+ */
+export function objectClean(obj: Record, options?: {cleanUndefined?: boolean, cleanNull?: boolean, deep?: boolean}): void {
+ mustBeObject(obj)
+ objectLoop(obj, (item, key) => {
+ if ((typeof options?.cleanUndefined === 'undefined' || options?.cleanUndefined) && item === undefined) {
+ delete obj[key]
+ }
+
+ if (options?.cleanNull && item === null) {
+ delete obj[key]
+ }
+
+ if ((typeof options?.deep === 'undefined' || options?.deep) && isObject(item)) {
+ return objectClean(item, options)
+ }
+ })
+}
+
+export function isObject(item: any): item is Record {
+ return typeof item === 'object' && item !== null
+}
+
+function mustBeObject(item: any): item is Record {
+ if (isObject(item)) {
+ return true
+ } else {
+ throw new Error("Input is not an object!")
+ }
+}
+
export default {
objectMap,
objectLoop,
@@ -196,5 +242,7 @@ export default {
cloneObject,
objectClone,
objectSet,
- objectEqual
+ objectEqual,
+ objectClean,
+ isObject
}