Challenge
My goal is to develop a function and its corresponding typing that can effectively split an array into multiple typed arrays inside a tuple. The concept involves calling the .divide method on an array instance, providing a flexible number of typeguards or typeguard-like functions. The output of divide should be a Tuple containing an equal number of typed arrays as the typeguards specified. Any items that do not match any of the provided typeguards will be removed from the result. Here's an example of how this could be used:
const [typeAs, typeBs, typeCs] = myArr.divide(isTypeA, isTypeB, isTypeC);
const [typeFs] = myArr.divide(isTypeF)
const [typeAs, typeFs, typeDs, typeCs, typeXYZs] = myArr.divide(isTypeA,isTypeF,isTypeD,isTypeC,isTypeXYZ)
//and so on
To start off, I've made an attempt at setting up a function for dividing into 3 types with potential for a variable length Tuple + arguments list. I've defined an interface for Array:
type TGuard<S> = ((input: any) => input is S) | ((input: any) => boolean);
divide<OrigType, NewT1, NewT2, NewT3>(
t1: TGuard<NewT1>,
t2: TGuard<NewT2>,
t3: TGuard<NewT3>,
): [NewT1[], NewT2[], NewT3[]];
Here's my implementation:
Array.prototype.divide = function <OGType, NewT1, NewT2, NewT3>(
t1: TGuard<NewT1>,
t2: TGuard<NewT2>,
t3: TGuard<NewT3>,
): [NewT1[], NewT2[], NewT3[]] {
const d3: [NewT1[], NewT2[], NewT3[]] = [[], [], []];
const discards: OGType[] = [];
this.forEach((item) => {
t1(item) ? d3[0].push(item) : t2(item) ? d3[1].push(item) : t3(item) ? d3[2].push(item) : discards.push(item);
});
return d3;
};
While this implementation works for 3 types, I'm struggling to extend it to accept a dynamic number of typeguards and generate a variable number of typed arrays within a Tuple wrapper. I have various ideas for the final implementation, but currently my biggest challenge lies in determining the appropriate type signature.