export default class HelperObject {
    public static clone<T extends any>(obj: T): T {
        if (obj === undefined || typeof (obj) !== "object") {
            return obj; // any non-objects are passed by value, not reference
        }
        if (obj instanceof Date) {
            return <any>new Date(obj.getTime());
        }
        const temp: any = new obj.constructor();
        Object.keys(obj).forEach(key => {
            temp[key] = HelperObject.clone(obj[key]);
        });
        return temp;
    }

    public static merge<T>(from: T, to: T, reverseArrays = false): T {
        for (const i in from) {
            if (from[i] instanceof Array && to[i] instanceof Array) {
                to[i] = reverseArrays ? (<any>from[i]).concat(to[i]) : (<any>to[i]).concat(from[i]);
            } else {
                to[i] = from[i];
            }
        }
        return to;
    }
}

export default class HelperObject {
    public static clone<T extends any>(obj: T): T {
        // We need to check strict null
        // tslint:disable-next-line
        if (obj === undefined || obj === null || typeof (obj) !== "object") {
            return obj; // any non-objects are passed by value, not reference
        }
        if (obj instanceof Date) {
            return <any>new Date(obj.getTime());
        }
        const temp: any = new obj.constructor();
        Object.keys(obj).forEach(key => {
            temp[key] = HelperObject.clone(obj[key]);
        });
        return temp;
    }

    public static merge<T>(from: T, to: T, reverseArrays = false): T {
        for (const i in from) {
            if (from[i] instanceof Array && to[i] instanceof Array) {
                to[i] = reverseArrays ? (<any>from[i]).concat(to[i]) : (<any>to[i]).concat(from[i]);
            } else {
                to[i] = from[i];
            }
        }
        return to;
    }

    public static extend<T extends any>(obj: T, template: any): T {
        Object.keys(template).filter(k => obj[k] === undefined).forEach(k => {
            obj[k] = this.clone(template[k]);
        });
        return obj;
    }
}

Implement HelperObject.extend() and fix a bug in .clone()
Implement HelperObject.extend() and fix a bug in .clone()
