76 lines
3.0 KiB
TypeScript
76 lines
3.0 KiB
TypeScript
export class DeepArray<T> extends Array<T> {
|
|
public constructor(array: T[]|Array<T>|DeepArray<T>) {
|
|
// console.log("Constructing DeepArray<T> with array =", array);
|
|
super();
|
|
this.push(...array);
|
|
}
|
|
public mapRecursive<FromT, ToT>(this: FromT[], callbackfn: (value: FromT, index: number, array: DeepArray<FromT>) => ToT, childrenPropertyName: string): DeepArray<ToT> | undefined {
|
|
if(!childrenPropertyName){
|
|
throw "mapRecursive requires parameter `childrenPropertyName`";
|
|
}
|
|
const result: DeepArray<ToT> = new DeepArray([]);
|
|
this.forEach((element: any) => {
|
|
if (Array.isArray(element[childrenPropertyName])) {
|
|
result.push(...(new DeepArray<FromT>(element[childrenPropertyName])).mapRecursive<FromT,ToT>(callbackfn, childrenPropertyName) as ToT[]);
|
|
} else {
|
|
result.push(callbackfn(element, 0, new DeepArray<FromT>(this)));
|
|
}
|
|
});
|
|
return result;
|
|
}
|
|
public findRecursive<T>(this: DeepArray<T>, 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<T>(childElements).findRecursive(predicate, childrenPropertyName);
|
|
}
|
|
return undefined;
|
|
}
|
|
public asArray<T>(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<Complex>([ { interestingProperty: 'a', recursiveChildren: [ { interestingProperty: 'b' } ] }]);
|
|
* // Example 1: Map from Complex to Simple.
|
|
* deepArray.mapRecursive<Complex, Simple>((complex) => complex.interestingProperty, 'recursiveChildren');
|
|
* // Example 2: Find an element deeply in the tree.
|
|
* let result = deepArray.findRecursive<Complex>((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<Complex>([ { interestingProperty: 'a', recursiveChildren: [ { interestingProperty: 'b' } ] }]);
|
|
// Example 1: Map from Complex to Simple.
|
|
deepArray.mapRecursive<Complex, Simple>((complex) => complex.interestingProperty, 'recursiveChildren');
|
|
// Example 2: Find an element deeply in the tree.
|
|
console.log("Checkpoint 3");
|
|
let result = deepArray.findRecursive<Complex>((complex) => complex.interestingProperty === 'b', 'recursiveChildren');
|