@angular-ru/cdk/object
sortByAsc
const objectList: A[] = [{ a: 1 }, { a: 3 }, { a: 2 }, { a: -1 }, { a: 0 }];
expect(objectList.slice().sort((a, b) => sortByAsc('a', a, b))).toEqual([
{ a: -1 },
{ a: 0 },
{ a: 1 },
{ a: 2 },
{ a: 3 }
]);
sortByDesc
const objectList: A[] = [{ a: 1 }, { a: 3 }, { a: 2 }, { a: -1 }, { a: 0 }];
expect(objectList.slice().sort((a, b) => sortByDesc('a', a, b))).toEqual([
{ a: 3 },
{ a: 2 },
{ a: 1 },
{ a: 0 },
{ a: -1 }
]);
isObject
- check inheritance of object
import { isObject } from '@angular-ru/cdk/object';
class A {}
expect(isObject(NaN)).toBe(false);
expect(isObject(null)).toBe(false);
expect(isObject(undefined)).toBe(false);
expect(isObject(1)).toBe(false);
expect(isObject(Infinity)).toBe(false);
expect(isObject('')).toBe(false);
// non primitive
expect(isObject([])).toBe(true);
expect(isObject({})).toBe(true);
expect(isObject(new A())).toBe(true);
expect(isObject(new Date())).toBe(true);
expect(isObject(new Map())).toBe(true);
expect(isObject(() => {})).toBe(true);
expect(isObject(new Number(6))).toBe(true);
expect(isObject(Math)).toBe(true);
expect(isObject(Object.create(null))).toBe(true);
expect(isObject(document.createElement('div'))).toBe(true);
expect(isObject(new (function Foo() {})())).toBe(true);
expect(isObject(window)).toBe(true);
isPlainObject
- check only literal object (non instance object)
import { isPlainObject } from '@angular-ru/cdk/object';
class A {}
expect(isPlainObject(NaN)).toBe(false);
expect(isPlainObject(null)).toBe(false);
expect(isPlainObject(undefined)).toBe(false);
expect(isPlainObject(1)).toBe(false);
expect(isPlainObject(Infinity)).toBe(false);
expect(isPlainObject('')).toBe(false);
// plain object
expect(isPlainObject({})).toBe(true);
expect(isPlainObject(Object.create(null))).toBe(true);
// complex object (not plain literal)
expect(isPlainObject([])).toBe(false);
expect(isPlainObject(new A())).toBe(false);
expect(isPlainObject(new Date())).toBe(false);
expect(isPlainObject(new Map())).toBe(false);
expect(isPlainObject(() => {})).toBe(false);
expect(isPlainObject(new Number(6))).toBe(false);
expect(isPlainObject(Math)).toBe(false);
expect(isPlainObject(document.createElement('div'))).toBe(false);
expect(isPlainObject(new (function Foo() {})())).toBe(false);
isSimpleObject
- check only instance object or literal (non complex structure - Array, DOM, Set, Map, Date, other structure)
import { isSimpleObject } from '@angular-ru/cdk/object';
class A {}
expect(isSimpleObject(NaN)).toBe(false);
expect(isSimpleObject(null)).toBe(false);
expect(isSimpleObject(undefined)).toBe(false);
expect(isSimpleObject(1)).toBe(false);
expect(isSimpleObject(Infinity)).toBe(false);
expect(isSimpleObject('')).toBe(false);
// instance object, literal object
expect(isSimpleObject(new A())).toBe(true);
expect(isSimpleObject(Object.create(null))).toBe(true);
expect(isSimpleObject({})).toBe(true);
expect(isSimpleObject(new (function Foo() {})())).toBe(true);
// complex object (Array, DOM, Set, Map, other structure)
expect(isSimpleObject([])).toBe(false);
expect(isSimpleObject(new Date())).toBe(false);
expect(isSimpleObject(new Map())).toBe(false);
expect(isSimpleObject(() => {})).toBe(false);
expect(isSimpleObject(new Number(6))).toBe(false);
expect(isSimpleObject(Math)).toBe(false);
expect(isSimpleObject(document.createElement('div'))).toBe(false);
isGetter
import { isGetter } from '@angular-ru/cdk/object';
class A {
public get a(): number {
return 1;
}
public b: string = '2';
}
expect(isGetter(new A(), 'a')).toEqual(true);
expect(isGetter(new A(), 'b')).toEqual(false);
expect(
isGetter(
{
get a() {
return 2;
}
},
'a'
)
).toEqual(true);
expect(
isGetter(
{
_a: null,
set a(value: any) {
this._a = value;
}
},
'a'
)
).toEqual(false);
expect(isGetter({ a: 2 }, 'a')).toEqual(false);
isIterable
expect(isIterable([1, 2])).toBe(true);
expect(isIterable('Some String')).toBe(true);
expect(isIterable(new Set([1, 2]))).toBe(true);
expect(
isIterable(
new Map([
['a', 1],
['b', 2]
])
)
).toBe(true);
expect(
isIterable(
new Map([
['a', 1],
['b', 2]
]).entries()
)
).toBe(true);
expect(isIterable({ a: 1, b: 2 })).toBe(false);
expect(isIterable(null)).toBe(false);
expect(isIterable(undefined)).toBe(false);
expect(isIterable(0)).toBe(false);
expect(isIterable(true)).toBe(false);
expect(isIterable(() => {})).toBe(false);
deepClone
import { deepClone } from '@angular-ru/cdk/object';
import { Origin } from './origin';
const origin: Origin = { a: 1, b: { c: 2 } };
const copy: Origin = deepClone(origin);
expect(Object.is(origin, copy)).toEqual(false);
copy.b.c = 4;
expect(origin.b.c).toEqual(2);
origin.b.c = 3;
expect(origin.b.c).toEqual(3);
expect(copy.b.c).toEqual(4);
deepFreeze
import { deepFreeze } from '@angular-ru/cdk/object';
import { Origin } from './origin';
const origin: Origin = deepFreeze({ a: 1, b: { c: 2 } });
let message: string | null = null;
try {
origin.b.c = 5;
} catch (e) {
message = e.message;
}
expect(message).toEqual(`Cannot assign to read only property 'c' of object '[object Object]'`);
replaceWithNull
import { PlainObject } from '@angular-ru/cdk/typings';
import { replaceWithNull } from '@angular-ru/cdk/object';
const wrongElem: PlainObject = {
a: '',
b: [
{ c: NaN, d: 1 },
{ c: ' ', d: undefined },
{ c: 0, d: 0 }
],
e: Infinity
};
expect(replaceWithNull(wrongElem)).toEqual({
a: null,
b: [
{ c: null, d: 1 },
{ c: null, d: null },
{ c: 0, d: 0 }
],
e: null
});
clean
import { PlainObject } from '@angular-ru/cdk/typings';
import { clean } from '@angular-ru/cdk/object';
const A: PlainObject = clean({
a: 1,
b: undefined,
c: '',
d: null,
e: NaN,
f: [
{
a: 2,
b: undefined,
c: '',
d: Infinity
},
{
a: 3,
b: undefined,
c: '',
d: Infinity
}
],
g: {
a: 4,
b: undefined,
c: '',
d: Infinity
},
h: Infinity
});
const B: PlainObject = { a: 1, f: [{ a: 2 }, { a: 3 }], g: { a: 4 } };
expect(A).toEqual(B);
getValueByPath
import { PlainObject } from '@angular-ru/cdk/typings';
import { getValueByPath } from '@angular-ru/cdk/object';
const obj: PlainObject = { a: 1, f: [{ a: 2 }, { a: 3 }], g: { a: 4 } };
expect(getValueByPath(obj, 'g.a')).toEqual(4);
expect(getValueByPath(obj, 'f.0')).toEqual({ a: 2 });
expect(getValueByPath(obj, 'f.0.a')).toEqual(2);
expect(getValueByPath(obj, 'abc')).toEqual(undefined);
expect(getValueByPath(obj, 'f.0.a.Z', [])).toEqual([]);
checkIsShallowEmpty
import { checkIsShallowEmpty } from '@angular-ru/cdk/object';
expect(checkIsShallowEmpty({ a: 0 })).toEqual(false);
expect(checkIsShallowEmpty({ a: { b: '' } })).toEqual(false);
expect(checkIsShallowEmpty({ a: 'hello' })).toEqual(false);
// shallow empty object
expect(checkIsShallowEmpty({})).toEqual(true);
expect(checkIsShallowEmpty({ a: null })).toEqual(true);
expect(checkIsShallowEmpty({ a: '', b: undefined, c: NaN, d: ' ' })).toEqual(true);
equals, objectToString, flatten, strictEquals, shallowTrimProperties
it('should be object A equals object B', (): void => {
const A: PlainObject = { a: 1, b: [1, 2] };
const B: PlainObject = { a: 1, b: [1, 2] };
expect(equals(A, B)).toBe(true);
});
it('should be not equals A and B when shallow comparison unsorted keys', (): void => {
const A: PlainObject = { a: 1, c: { e: 2, d: 1 }, b: [1, 2] };
const B: PlainObject = { b: [1, 2], a: 1, c: { d: 1, e: 2 } };
expect(equals(A, B)).toBe(false);
});
it('should be not equals A and B when deep comparison unsorted keys', (): void => {
const A: PlainObject = { a: 1, c: { e: 2, d: 1 }, b: [1, 2] };
const B: PlainObject = { b: [1, 2], a: 1, c: { d: 1, e: 2 } };
const D: PlainObject = { a: 1, b: 2, c: [{ e: 2, d: 1 }] };
const E: PlainObject = { a: 1, b: 2, c: [{ d: 1, e: 2 }] };
expect(equals(A, B, { deep: true })).toBe(true);
expect(equals(D, E, { deep: true })).toBe(true);
});
it('should be return true for equals primitive types', (): void => {
expect(equals(null!, null!)).toBe(true);
expect(equals(undefined!, undefined!)).toBe(true);
expect(equals(NaN as NaN as any)).toBe(true);
expect(equals(Infinity as Infinity as any)).toBe(true);
expect(equals('' as '' as any)).toBe(true);
expect(equals(1 as 1 as any)).toBe(true);
expect(equals('1' as 1 as any)).toBe(false);
expect(equals(null!, undefined!)).toBe(false);
expect(equals(NaN as !undefined, { deep: true })).toBe(false);
});
it('should be a proper comparison with a weak and strict type', (): void => {
expect(equals({ a: '1' }, { a: 1 })).toBe(false);
expect(equals({ a: '1' }, { a: 1 }, { weekType: true })).toBe(true);
});
it('should be correct work objectToString', (): void => {
expect(objectToString(1 as any)).toBe('1');
expect(objectToString('1' as any)).toBe('"1"');
expect(objectToString(null!)).toBe('null');
expect(objectToString(undefined!)).toBe(undefined);
expect(objectToString({ a: 1, b: 2 })).toBe('{"a":1,"b":2}');
expect(objectToString([{ b: 2, a: 1 }])).toBe('[{"b":2,"a":1}]');
expect(objectToString([{ b: 2, a: 1 }], { deep: true })).toBe('[{"a":1,"b":2}]');
expect(objectToString({ a: 1, b: 2, c: [{ e: 2, d: 1 }] })).toBe('{"a":1,"b":2,"c":[{"e":2,"d":1}]}');
expect(objectToString({ a: 1, b: 2, c: [{ e: 2, d: 1 }] }, { deep: true })).toBe(
'{"a":1,"b":2,"c":[{"d":1,"e":2}]}'
);
});
it('should be correct flatten object', (): void => {
const actual: PlainObject = {
a: {
b: 1,
c: {
d: 2
},
d: [{ e: 3 }, { f: 4 }]
},
g: 5
};
const expected: PlainObject = { 'a.b': 1, 'a.c.d': 2, 'a.d.0.e': 3, 'a.d.1.f': 4, g: 5 };
expect(flatten<number>(actual)).toEqual(expected);
});
it('should be correct deep equals with week type', (): void => {
expect(
strictEquals(
{
a: 1,
b: 2,
c: { d: { f: { g: 'd' } } }
},
{
a: 1,
b: 2,
c: { d: { f: { g: 'i' } } }
}
)
).toEqual(false);
expect(
strictEquals(
{
a: null,
b: undefined,
c: NaN
},
{
a: null,
b: null,
c: null
}
)
).toEqual(true);
expect(
strictEquals(
{
a: null,
b: undefined
},
{
a: null,
b: null,
c: null
}
)
).toEqual(false);
});
shallowMapObject
import { shallowMapObject } from '@angular-ru/cdk/object';
const oneTypeObject = { a: 1, b: 3, c: 5 };
expect(shallowMapObject(oneTypeObject, (a: number): number => a * 2)).toEqual({
a: 2,
b: 6,
c: 10
});
const complexObject = { a: 1, b: 'two', c: true, d: undefined, e: null, f: { field: 'value' }, g: [1, 2, 3] };
expect(shallowMapObject(complexObject, (a): string => JSON.stringify(a))).toEqual({
a: '1',
b: '"two"',
c: 'true',
d: undefined,
e: 'null',
f: '{"field":"value"}',
g: '[1,2,3]'
});
Last updated