question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. ItĀ collects links to all the places you might be looking at while hunting down a tough bug.

And, if youā€™re still stuck at the end, weā€™re happy to hop on a call to see how we can help out.

Deeper inference of Promise types.

See original GitHub issue

Suggestion

šŸ” Search Terms

promise required infer label:Suggestion

āœ… Viability Checklist

My suggestion meets these guidelines:

  • This wouldnā€™t be a breaking change in existing TypeScript/JavaScript code
  • This wouldnā€™t change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isnā€™t a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
  • This feature would agree with the rest of TypeScriptā€™s Design Goals.

ā­ Suggestion

In TypeScript 4.1 the first argument of a promiseā€™s resolve function was made to be required rather than optional (see this blogpost). This is useful because it often catches legitimate bugs. The downside is that you always have to provide a type argument. It would be nice if TypeScript were better at inferring the types of Promises so that you donā€™t always have to provide a type. So for instance

new Promise(r => r(3));

Would automatically result in the type Promise<number>.

šŸ“ƒ Motivating Example

In TypeScript having to provide a type is not such a big deal. You can usually get away with something like:

await new Promise<number>(r => r(3));

But in Javascript with JSDoc, this same piece of code becomes:

/** @type {Promise<number>} */
const promise = new Promise(r => r(3);
await promise;

which is generally a lot less clean and less readable than the TypeScript equivalent.

šŸ’» Use Cases

I frequently find myself running across code like the following:

/** @type {(() => void)[]} */
const cbs = [];

async function test() {
    // Do something

    // wait until `cbs` have fired
    await new Promise(r => r());

    // Do something else
}

All I want to do here is wait in the middle of an async function until a certain event has happened and then move on. I wonā€™t even be using the return value of the promise most of the time.

But because the first argument is required, TypeScript will now complain that Iā€™m calling r() without any arguments. (hereā€™s a playground example)

If the return type of the promise would be inferred, thereā€™ wouldnā€™t be the need to create an extra variable and annotate the promise with the Promise<void> type.

Issue Analytics

  • State:open
  • Created a year ago
  • Reactions:2
  • Comments:6 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
fatcerberuscommented, Jun 4, 2022

@DarkGuy10 While this doesnā€™t invalidate the feature request, itā€™s worth noting that in cases like yours you can take advantage of contextual typing:

	/**
	 * Wait for the client to get ready.
	 */
	async getReady(): Promise<void> {
		return new Promise(resolve => {
			this.once('ready', () => {
				resolve()
			})
		})
	}

Assigning a new Promise() to an existing Promise type automatically infers the correct type for resolve.

P.S. this method probably doesnā€™t need to be marked async since it returns a promise directly and never uses await. You generally want to avoid that because it imposes an extra layer of promise-wrapping and by extension, extra event loop ticks.

1reaction
DarkGuy10commented, Jun 4, 2022

Came across this while creating a promise that just needs to resolve on an event (donā€™t need a value)

	/**
	 * Wait for the client to get ready.
	 */
	async getReady(): Promise<void> {
		const promise = new Promise<void>(resolve => {
			this.once('ready', () => {
				resolve()
			})
		})
		return promise
	}

Would save trouble if resolve types were automatically inferred

Read more comments on GitHub >

github_iconTop Results From Across the Web

TypeScript 2.1 RC: Better Inference, Async Functions, and More
With TypeScript 2.0 we built out a foundation of using control flow analysis to track the flow of types throughout your program. Because...
Read more >
TypeScript: Incorrect type inference in Promise.all
Because the array passed to Promise.all isn't being typed explicitly, it's inferred to be a union of all its value types:
Read more >
Type Inference
Type Inference. Goal: Given unannotated program, find its type or report it does not type check. Overview: generate type constraints (equations) fromĀ ...
Read more >
Under the hood of Futures and Promises in Swift
Our Promise type will be a subclass of Future that adds APIs for resolving and rejecting it. Resolving a promise results in the...
Read more >
Inferences and Conclusions | Cuesta College - Cuesta College
Using these clues to give you a deeper understanding of your reading is called inferring. When you infer, you go beyond the surface...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found