-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Description
The typings for both flat and flatMap work ok for homogeneous arrays but do not handle tuple types well. Consider the current typings (with rename):
declare let arr: [[number, boolean], string];
let x0 = arr.flatten(0); // (string | [ number, boolean ])[]
let x1 = arr.flatten(1); // error
let x2 = arr.flatten(2); // error
Using conditional types and infer
we can start to see a solution like:
type Flatten0<T> = T extends Array<infer U> ? Array<U> : never;
type Flatten1<T> = T extends Array<infer U>
? U extends Array<any> ? Flatten0<U> : never
: never;
type Flatten2<T> = T extends Array<infer U>
? U extends Array<any> ? Flatten1<U> : never
: never;
interface Array<T> {
flat<T>(this: T, depth: 2): Flatten2<T>;
flat<T>(this: T, depth: 1): Flatten1<T>;
flat<T>(this: T, depth: 0): Flatten0<T>;
flat<T>(this: T, depth: number): Array<T>
}
Which works great for array types and handles some tuple types better, but sacrifices a type error on the depth parameter when the array isn't nested that much, and more importantly, doesn't handle heterogeneous tuple cases, e.g. [ [string, number], boolean]
should flatten to [string, number, boolean]
. As far as I can tell, this is not possible without variadic kinds. Additionally, this implementation would benefit hugely from a way to reference a type recursively, e.g. https://github.com/Microsoft/TypeScript/issues/6230 (I'm not the only one to notice this issue trying to type this API).