Typescript: Expansion of a generic type with Promise not working in VsCode (and in PlayGroung) 'type X<T> = () => T | Promise<T>;'

Created on 24 May 2020  路  11Comments  路  Source: microsoft/TypeScript

TypeScript Version: 3.9.2 or 4.0.0-dev.20200523 or 3.3.3333

Code

export const TypeScript = "v3.9.2";

export class MaybeList<T> {
  public constructor(public value: T) {}
}

// type T_<T> = T
export type T_<T> = T;
// type M_<T> = MaybeList<T>
export type M_<T> = T_<MaybeList<T>>;
// type P_<T> = Promise<T>
export type P_<T> = T_<Promise<T>>;
// type MP_<T> = MaybeList<Promise<T>>
export type MP_<T> = M_<P_<T>>;
// type PM_<T> = Promise<MaybeList<T>>
export type PM_<T> = P_<M_<T>>;
// type PMP_<T> = Promise<MaybeList<Promise<T>>>
export type PMP_<T> = P_<M_<P_<T>>> | P_<MP_<T>> | PM_<P_<T>>;
// type P_T<T> = T | Promise<T>
export type P_T<T> =  T | P_<T>;
// type P_M_<T> = MaybeList<T> | Promise<MaybeList<T>>
export type P_M_<T> = (M_<T> | PM_<T>) | P_T<M_<T>>;
// type P_MP_<T> = MaybeList<Promise<T>> | Promise<MaybeList<Promise<T>>>
export type P_MP_<T> = (MP_<T> | PMP_<T>) | P_T<MP_<T>>;

// type _T_<T> = () => T
export type _T_<T> = () => T_<T_<T>>;
// type _M_<T> = () => MaybeList<T>
export type _M_<T> = () => T_<M_<T>>;
// type _P_<T> = () => Promise<T>
export type _P_<T> = () => T_<P_<T>>;
// type _MP_<T> = () => MaybeList<Promise<T>>
export type _MP_<T> = () => T_<MP_<T>>;
// type _PM_<T> = () => Promise<MaybeList<T>>
export type _PM_<T> = () => T_<PM_<T>>;
// type _PMP_<T> = () => Promise<MaybeList<Promise<T>>>
export type _PMP_<T> = () => T_<PMP_<T>>;
// type _P_T<T> = () => P_T<T>
export type _P_T<T> = () => P_T<T>;
// type _P_M_<T> = () => MaybeList<T> | Promise<MaybeList<T>>
export type _P_M_<T> = () => T_<P_M_<T>>;
// type _P_MP_<T> = () => MaybeList<Promise<T>> | Promise<MaybeList<Promise<T>>>
export type _P_MP_<T> = () => T_<P_MP_<T>>;

Expected behavior:
I would like to get it expanded like this: type _P_T<T> = () => T | Promise<T>

should be similar to: type _PMP_<T> = () => Promise<MaybeList<Promise<T>>>
image

or should be similar to: type P_T<T> = T | Promise<T>
image

Actual behavior:
Not expanding the P_T into T | Promise<T>
image

the P_ here is for Promise and all other types I have made in the same module are showing Promise Keyword expanded except on the line 46~47 (in the playground link below)
// expansion: type _P_T<T> = () => P_T<T> should be: type _P_T<T> = () => T | Promise<T>
export type _P_T<T> = () => P_T<T>;

Playground Link:
PlayGround Link v3.9.2

Needs More Info

All 11 comments

I was working on a project and I realize that some type may have been simplified but the mater of my request is only regarding the export type _P_T<T> = () => P_T<T> (which also for consistency should have been P_T_ instead of P_T. The leading underscore denotes the use or not of an arrow function as in _P_T)

overview without the comments:
image

TLDR version:

Code:

type MaybePromise<T> = T | Promise<T>
type AsReturnType<T> = () => MaybePromise<T>

Expected:

Hover over symbol AsReturnType, see type AsReturnType<T> = () => T | Promise<T>.

Actual:

Hover over symbol AsReturnType, see type AsReturnType<T> = () => MaybePromise<T>.

Playground:

https://www.typescriptlang.org/play/#code/C4TwDgpgBAsghiARhACgJwPYFsCWBnCAHgBUA+KAXimKgB8p1t8iyAoUSKAQTwCUJgAVzQA7YuBbkqACgCUlcvCSpMuAiVKsgA

Reasoning:

Most of the other cases (unions and whatnot; see original post) expanded and de-duped types for hover, so the "base" Promise types could be seen.

I'm personally not sure what's the "best" behaviour here, but first instinct says it should have somewhat consistent hover expansion behavior.

HO my god tanks I will do an effort to never do something like this again (I feel so ridicule tanks @AviVahl)

TLDR version:

Code:

type MaybePromise<T> = T | Promise<T>
type AsReturnType<T> = () => MaybePromise<T>

[...]

I don't understand the wall of text and I don't understand the example. Where is AsCallback defined? That's not a built-in; it shouldn't appear in any hovers

@RyanCavanaugh I had typos when renaming stuff, which broke the example. Check out the current expected/actual (my previous comment).

I don't understand the wall of text and I don't understand the example. Where is AsCallback defined? That's not a built-in; it shouldn't appear in any hovers

I am not as good as you to explain myself I still would like to be able to express my problem.

Here is another version of the problem

This problem is more concrete also the type _P_T<T> = () => T | Promise<T> have been renamed to be type _T_PT_<T> = () => T | Promise<T> and the version below (_without leading underscore_) is not function (don't have the () => part)...

I want to be able to work with something like type T_PT_<T> = T | Promise<T> (type T_PT_ means to me 'Tee' or Promise of 'Tee') but somewhere in my code the "T" is already T = Promise<Tee> where Tee could be anything that T would be instead of it being wrapped in a promise ("Tee" is another "T" different because it is somewhere else in the code but which should be the same "T" instead of "Tee" enclosed inside of a promise)

I want to use a function valueMap_P and using generic type to extract the "T" as in Tx = MaybeList<HMSETResult>> istead of as in Ty = Promise<MaybeList<HMSETResult>> I expect to get a "value or promiseOf" because I use a promisseOf function the code of the function in below a screenshot of it:

2020-06_20200624_081305_0001

export async function promisseOf<V>(value: V | Promise<V>): Promise<V> {
  return Promise.resolve(value).then(async x => x);
}

The MaybeList type is similar to an Array on which I would like to use a reduce method the mouse over code is below the screenshot of it which include an error message I would like to go away:

2020-06_20200624_080302_0001

const valueMap_P: <Promise<MaybeList<HMSETResult>>>(value: T_PT_<Promise<MaybeList<HMSETResult>>>) => ValueMap_P<Promise<MaybeList<HMSETResult>>>
First provide a value<T> (value or promiseOf) and get a ValueThenMap. Then pass a mapFunction will return a Promise<R> (property) valueMap_P

2020-06_20200624_114538_0001

Also, I am not sure how I should interpret this problem: const step7: Promise<Promise<MaybeList<HMSETResult>>> how can I remove the Promise<Promise<any>> right now I must do: step7.then(async x=>x)

the async keyword is optional but I use typescript-eslint/promise-function-async which requires any function or method that returns a Promise to be marked async...

I think the issue I have opened here is not directly related to this problem but I need to do const step7b = step7.then(async x=>x) before I put the now step7b into a function that takes care of the promise anyway ...

I think this is related to my #37664

My understanding here has not improved 馃槙

I feel like I should be closing this issue until I can explain myself more clearly.

I must learn how to be more concise it seems. I will use TypeScript the way it is until I can bring my ideas or explain my issues in a more constructive and helpful manner.

Was this page helpful?
0 / 5 - 0 ratings