Skip to content

Handle heterogeneous arrays in flat and flatMap #24579

@bterlson

Description

@bterlson

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).

Metadata

Metadata

Assignees

No one assigned

    Labels

    Domain: lib.d.tsThe issue relates to the different libraries shipped with TypeScriptES NextNew featurers for ECMAScript (a.k.a. ESNext)Help WantedYou can do thisSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions