interface Object {
    path<A>
        (this: A): A | undefined
    path<A, B extends keyof A>
        (this: A, key: B): A[B] | undefined
    path<A, B extends keyof A, C extends keyof A[B]>
        (this: A, key1: B, key2: C): A[B][C] | undefined 
    path<A, B extends keyof A, C extends keyof A[B], D extends keyof A[B][C]>
        (this: A, key1: B, key2: C, key3: D): A[B][C][D] | undefined 
    path<A, B extends keyof A, C extends keyof A[B], D extends keyof A[B][C], E extends keyof A[B][C][D]>
        (this: A, key1: B, key2: C, key3: D, key4: E): A[B][C][D][E] | undefined 
    path<A, B extends keyof A, C extends keyof A[B], D extends keyof A[B][C], E extends keyof A[B][C][D], F extends keyof A[B][C][D][E]>
        (this: A, key1: B, key2: C, key3: D, key4: E, key5: F): A[B][C][D][E][F] | undefined
    path<A, B extends keyof A, C extends keyof A[B], D extends keyof A[B][C], E extends keyof A[B][C][D], F extends keyof A[B][C][D][E], G extends keyof A[B][C][D][E][F]>
        (this: A, key1: B, key2: C, key3: D, key4: E, key5: F, key6: G): A[B][C][D][E][F][G] | undefined
}


Object.prototype.path = function(this: any | undefined, ...keys: string[]): any | undefined {
    let current = this
    for(let i=0; current !== undefined && current !== null && i < keys.length; i++) {
        current = current[keys[i]]
    }
    return current
}


// interface Array<T> {
//     get(index: number): T | undefined
// }
// Array.prototype.get = function<T>(index) { return (this !== undefined && this !== null && this.length > index) ? this[index]  : undefine