TypeScript: 3.7-beta regression: Promise.all wrongly adds `undefined` type

TypeScript Version: 3.7.0-beta

Search Terms:

promise all

Code

interface A {
  a: string
}
interface B {
  b: string
}
async function main(): Promise<A> {
  const [a, b] = await Promise.all([
    Promise.resolve({a: "a"} as A),
    Promise.resolve({b: "b"} as B | undefined), // <- the `| undefined` here is the problem
  ]);
  return a; // <- a has type `A | undefined`, but should be `A`
}

Expected behavior:

This is a regression from 3.6.3, where the return tuple of Promise.all is correctly inferred.

Actual behavior:

A | undefined bound of a different tuple member also adds a | undefined bound on a different unrelated return value of Promise.all.

Playground Link:

https://www.typescriptlang.org/play/?ts=3.7-Beta#code/JYOwLgpgTgZghgYwgAgILIN4ChnLgLmQGcwpQBzLAXy1ElkRQCFMdkAjQkskSmuIgE8QCZDACuIsMAD2IZAFs4oABQBKQgAUoMhcCIQAPKgB8rXAjklkAbTgAaDgF1kAXjwB3ZWGTbd+iAA6OAAbEJUbNlw-PQNAqAgiGRCANwgVDAJkACI4bKo8IjQ1eyjfHVighKTU9IxOHPZ8wuQWAB9kSQATCBhQCC6S5AB6YeRDAFpkMAALFAADDu7e-q755DmE5H1pueQABx12EIgFNic1AG42BLBxKHk4S5GxybwNgWnBfYX0JZAen0QAN5o52OIfEQZjJxCEuhxfvNqEA

Related Issues:

Maybe https://github.com/microsoft/TypeScript/pull/33707 ?

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 57
  • Comments: 25 (4 by maintainers)

Commits related to this issue

Most upvoted comments

@RyanCavanaugh What’s the timeline for getting this fixed? It’s been around for a while now, and it’s a pretty major regression, blocking us from upgrading…

We are having this issue in 3.7.3 as well. It is blocking our upgrade off of 3.6.x (hundreds of occurrences across the code base).

sed -i 's|: readonly|:|g' node_modules/typescript/lib/lib.es2015.promise.d.ts seems to be an effective temporary workaround until this is fixed.

Is there any reason my fix from November (quoted above) can’t or shouldn’t be used?

I don’t mind continuing to patch TypeScript in my own projects as a temporary workaround, but it just seems odd that such a high-impact regression with a simple quick fix available is still an issue three months later.

tbh, I’m a bit disappointed by the lack of communication here. I recently read the already month old Design notes here: https://github.com/microsoft/TypeScript/issues/36138 which mention ideas to create a dedicated awaited or promised type, which would maybe solve this, but is probably a very invasive change. However, this is just speculation on my part. Some official clarification would be nice.

@JasonKleban This is a legit regression. Just updated a codebase and am seeing this.

Easily reproducible:

const [num1, num2] = await Promise.all([Promise.resolve(1), Promise.resolve(null)]); Causes the type for num1 to be number | null.

@buu700 how do you recommend using that work around? running that command prior to compile every time?

@RyanCavanaugh this seems like a pretty major regression, is there any timeline here? I see this immediately on upgrading all around my code base.

Just checked on 3.9.0-dev.20200317 and it appears to be fixed. woohoo!

We anticipate that our next version, TypeScript 3.9, will be coming mid-May of 2020, and will mostly focus on performance, polish, and potentially smarter type-checking for Promises.

Hopefully this issue will be fixed in 3.9

This issue can be worked around by adding this somewhere:

declare global {
	interface PromiseConstructor {
		all<T extends readonly any[] | readonly [any]>(values: T): Promise<{ -readonly [P in keyof T]: Awaited<T[P]> }>;
	}
}

but I’d be really happy having this fixed, my devs are using this as an excuse to plaster Bluebird everywhere instead of using native promises.

Still exists in 3.9.0-dev.20200229

Seems this example still does not work on nightly.

(async () => {
    const [num1, num2] = await Promise.all([Promise.resolve(1), Promise.resolve(null)]);
    num1.toString();
})

Is it really fixed?

Assuming we merge the awaited type PR, I plan to take a renewed look at all of the Promise-related issues in light of that change.

v3.7.5 02.20 and I still facing the same issue on PromiseLike types via lib.es5.d.ts

Is this not a real issue? I’m getting it, and it seems to me that it is generally pretty disruptive, but I’m not seeing enough MS chatter about it to confirm that it’s not just a legit new type error that I don’t understand.

@buu700 this is amazing. thank you so much for the suggestion extremely helpful!

Yes, the typings in #33707 fix the smaller repro above.