Skip to content

Commit

Permalink
feat(implement extend in hub-common): implement extend
Browse files Browse the repository at this point in the history
Implements extend in \`hub-common\`, which extends a target object with props from a source object,
overwriting identically named props in target with those from source. Ignores null and undefined
values, similar to $.extend.

AFFECTS PACKAGES:
@esri/hub-common
  • Loading branch information
Robert Steilberg committed Sep 10, 2019
1 parent 5339379 commit 5e0ff68
Show file tree
Hide file tree
Showing 2 changed files with 175 additions and 1 deletion.
30 changes: 30 additions & 0 deletions packages/common/src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,3 +278,33 @@ export function camelize(value: string): string {
export function unique(value: any, index: number, ary: any[]): boolean {
return ary.indexOf(value) === index;
}

/**
* Extends the target object with props from the source object, overwriting identically named
* props in target with those from source, ignoring null and undefined values; similar to $.extend
*
* @param target - the object that will take props from source
* @param source - the object from which to take props
* @param deepExtend - whether or not to perform a deep (recursive( extend of source
*/
export function extend(
target: { [index: string]: any },
source: { [index: string]: any },
deepExtend: boolean = false
): { [index: string]: any } {
const extended: { [index: string]: any } = cloneObject(target);
return Object.keys(source).reduce((obj, prop) => {
if (source[prop] !== null && source[prop] !== undefined) {
const value = cloneObject(source[prop]);
if (Array.isArray(value)) {
// check for arrays, since array is type object
obj[prop] = value;
} else if (deepExtend && typeof value === "object") {
obj[prop] = extend(obj[prop] || {}, value, deepExtend);
} else {
obj[prop] = value;
}
}
return obj;
}, extended);
}
146 changes: 145 additions & 1 deletion packages/common/test/util.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import {
createId,
maybeAdd,
maybePush,
unique
unique,
extend
} from "../src/util";

describe("util functions", () => {
Expand Down Expand Up @@ -518,4 +519,147 @@ describe("util functions", () => {
expect([].filter(unique)).toEqual([]);
});
});

/* tslint:disable */
describe("extend", () => {
it("should extend an object", () => {
const target = {
a: 1
};
const source = {
a: "foo",
b: "bar"
};
const result = extend(target, source);
expect(result).toEqual({ a: "foo", b: "bar" });
});
it("should ignore null and undefined values", () => {
const target = {
a: 1,
b: 2,
c: 3
};
const source: any = {
a: undefined,
b: null,
c: 58
};
const result = extend(target, source);
expect(result).toEqual({ a: 1, b: 2, c: 58 });
});
it("should shallow extend a deep object", () => {
const target = {
a: 1,
b: {
c: 3
}
};
const source = {
a: "foo",
b: {
d: 5
}
};
const result = extend(target, source);
expect(result).toEqual({ a: "foo", b: { d: 5 } });
});
it("should deep extend a deep object", () => {
const target = {
a: 1,
b: {
c: 3
}
};
const source = {
a: "foo",
b: {
d: 5
}
};
const result = extend(target, source, true);
expect(result).toEqual({ a: "foo", b: { c: 3, d: 5 } });
});
it("should shallow extend an object with an array", () => {
const target = {
a: [1, 2, 3],
b: {
c: 3
}
};
const source = {
a: [4, 5, 6],
b: {
d: [6, 7, 8]
}
};
const result = extend(target, source);
expect(result).toEqual({ a: [4, 5, 6], b: { d: [6, 7, 8] } });
});
it("should return a new instance", () => {
const target = {
a: 1
};
const source = {
a: 3
};
const result = extend(target, source);
expect(result == target).toBeFalsy();
expect(result == source).toBeFalsy();
});
it("should deep extend a complex object", () => {
const fun = function() {};
const target = {
a: 1,
b: [2, 3],
c: {
d: 4,
e: [5, 6],
f: {
g: 7,
h: function() {},
i: [9, 10]
}
},
k: 58
};
const source: any = {
a: "1",
c: {
d: "4",
e: [12, 13],
f: {
g: ["11", "12"],
h: 8,
i: [9, 10],
j: fun,
l: null
},
r: {
o: 3
}
},
k: undefined
};
const expected = {
a: "1",
b: [2, 3],
c: {
d: "4",
e: [12, 13],
f: {
g: ["11", "12"],
h: 8,
i: [9, 10],
j: fun
},
r: {
o: 3
}
},
k: 58
};
const result = extend(target, source, true);
expect(result).toEqual(expected);
});
});
});

0 comments on commit 5e0ff68

Please sign in to comment.