export class DeepArray extends Array { public constructor(array: T[]|Array|DeepArray) { // console.log("Constructing DeepArray with array =", array); super(); this.push(...array); } public mapRecursive(this: FromT[], callbackfn: (value: FromT, index: number, array: DeepArray) => ToT, childrenPropertyName: string): DeepArray | undefined { if(!childrenPropertyName){ throw "mapRecursive requires parameter `childrenPropertyName`"; } const result: DeepArray = new DeepArray([]); this.forEach((element: any) => { if (Array.isArray(element[childrenPropertyName])) { result.push(...(new DeepArray(element[childrenPropertyName])).mapRecursive(callbackfn, childrenPropertyName) as ToT[]); } else { result.push(callbackfn(element, 0, new DeepArray(this))); } }); return result; } public findRecursive(this: DeepArray, predicate: (value: T) => boolean, childrenPropertyName: string): T | undefined { if(!childrenPropertyName){ throw "findRecursive requires parameter `childrenPropertyName`"; } let initialFind = this.find(predicate); if (initialFind) { return initialFind; } let elementsWithChildren = this.asArray().filter((x: any, index: number, array: T[]) => { return x[childrenPropertyName] }); if (elementsWithChildren.length) { let childElements: T[] = []; elementsWithChildren.forEach((x: any) => { if (x[childrenPropertyName]) childElements.push(...x[childrenPropertyName]); }); return new DeepArray(childElements).findRecursive(predicate, childrenPropertyName); } return undefined; } public asArray(this: T[]): T[] { let a: T[] = []; a.push(...this); return a; } } /** * @example * // How to use this module: * // Example usage: * type Simple = string; * interface Complex { * interestingProperty: Simple; * recursiveChildren?: Complex[]; * } * let deepArray = new DeepArray([ { interestingProperty: 'a', recursiveChildren: [ { interestingProperty: 'b' } ] }]); * // Example 1: Map from Complex to Simple. * deepArray.mapRecursive((complex) => complex.interestingProperty, 'recursiveChildren'); * // Example 2: Find an element deeply in the tree. * let result = deepArray.findRecursive((complex) => complex.interestingProperty === 'b', 'recursiveChildren'); */ // How to use this module: // Example usage: type Simple = string; interface Complex { interestingProperty: Simple; recursiveChildren?: Complex[]; } let deepArray = new DeepArray([ { interestingProperty: 'a', recursiveChildren: [ { interestingProperty: 'b' } ] }]); // Example 1: Map from Complex to Simple. deepArray.mapRecursive((complex) => complex.interestingProperty, 'recursiveChildren'); // Example 2: Find an element deeply in the tree. console.log("Checkpoint 3"); let result = deepArray.findRecursive((complex) => complex.interestingProperty === 'b', 'recursiveChildren');