Skip to content

Homomorphic mapped types can't work on arrays while using constrained helper types #27375

Closed
@DanielRosenwasser

Description

@DanielRosenwasser

I'm on TypeScript 3.1, and @bterlson asked if there was a way to construct all constructors inside of an array. However, trying to do this in a way that worked for object properties as well as array-likes seems impossible

type ConstructAll<T> = {
    [K in keyof T]: InstanceType<T[K]>
};

type Foo = ConstructAll<[typeof Date, typeof RegExp]>;

This gives an error on the first type argument to InstanceType:

[ts] Type 'T[K]' does not satisfy the constraint 'new (...args: any[]) => any'.

Ugh. Okay, fine.

type AnyConstructor = new (...args: never[]) => unknown;

type ConstructAll<T extends Record<string, AnyConstructor>> = {
    [K in keyof T]: InstanceType<T[K]>
};

type Foo = ConstructAll<[typeof Date, typeof RegExp]>;

Which gives me an error on the first type argument to ConstructAll:

[ts]
Type '[Date, RegExp]' does not satisfy the constraint 'Record<string, new (...args: any[]) => any>'.
  Index signature is missing in type '[Date, RegExp]'.

I'll save you time; the following doesn't work either:

type AnyConstructor = new (...args: never[]) => unknown;

type ConstructAll<T extends AnyConstructor[] | Record<string, AnyConstructor>> = {
    [K in keyof T]: InstanceType<T[K]>
};

type Foo = ConstructAll<[typeof Date, typeof RegExp]>;

You end up with the original scenario. I end up not being able to reuse InstanceType at all because it has a constraint that we can't dive into. I have to instead use some unconstrained conditional type.

type Constructor<T> = new (...args: any[]) => T;

type ConstructAll<T extends Constructor<unknown>[] | Record<string, Constructor<unknown>>> = {
    [K in keyof T]: T[K] extends Constructor<infer T> ? T : never;
};

type Foo = ConstructAll<[typeof Date, typeof RegExp]>

It seems problematic that we didn't want to "split the world" into array mapped types and object mapped types, but you end up with that problem anyway in some cases.

Metadata

Metadata

Assignees

No one assigned

    Labels

    QuestionAn issue which isn't directly actionable in code

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions