Type mapping to allow every value to be promise

37 Views Asked by At

I try to create a maped type that replace every property/element of array with an optional promise (recursive).

I came up with following mapping

type DeepPromise<T> = T extends Promise<infer K>
    ? Promise<DeepPromise<K>>
    : T extends Array<infer J>
    ? Array<DeepPromise<J>> | Array<Promise<DeepPromise<J>>> | Promise<Array<DeepPromise<J>>> | Promise<Array<Promise<DeepPromise<J>>>>
    : T extends object ? Promise<{
        [P in keyof T]: DeepPromise<T[P]>;
    }> | {
        [P in keyof T]: DeepPromise<T[P]>;
    } : Promise<T> | T;

and the reverse type

type WaitAlll<T> = T extends Promise<infer K>
    ? WaitAlll<K>
    : T extends Array<infer J>
    ? Array<WaitAlll<J>>
    : T extends object
    ? { [P in keyof T]: WaitAlll<T[P]>; }
    : T;

and a function to wait resolve every promise

function waitAll<T>(obj: T): Promise<WaitAlll<T>>  {...}

The Method seems to work but the typemapping seems off...

If I have following types

export type simpleType = simpleTypeFoo | simpleTypeBar;

export type simpleTypeFoo = {
    subType: 'foo'
}

export type simpleTypeBar = {
    subType: 'bar',
}

And try to Assign a Promise<simpleType> to variable of DeepPromise<simpleType> it shows an error.

let x1: DeepPromise<simpleType>;
let x2: Promise<simpleType>
x1 = x2; // error

Type 'Promise<simpleType>' is not assignable to type 'Promise<{ subType: "foo" | Promise<"foo">; }> | { subType: "foo" | Promise<"foo">; } | Promise<{ subType: "bar" | Promise<"bar">; }> | { ...; }'.
  Type 'Promise<simpleType>' is not assignable to type 'Promise<{ subType: "foo" | Promise<"foo">; }>'.
    Type 'simpleType' is not assignable to type '{ subType: "foo" | Promise<"foo">; }'.
      Type 'simpleTypeBar' is not assignable to type '{ subType: "foo" | Promise<"foo">; }'.
        Types of property 'subType' are incompatible.
          Type '"bar"' is not assignable to type '"foo" | Promise<"foo">'.ts(2322)

But I can assign a Promise<simpleTypeFoo> to variable of DeepPromise<simpleType> (also the other one).

I assume the union type is not correctly handled in the typemapping, but I'm not sure how to fix it...

0

There are 0 best solutions below