Skip to content

(ES2024) The resolving function in Promise.withResolvers() is not allowed to be passed no arguments (void) unless explicitly specified #63028

@rugk

Description

@rugk

🔎 Search Terms

  • Promise.withResolvers

🕗 Version & Regression Information

⏯ Playground Link

https://www.typescriptlang.org/play/?target=99#code/MYewdgziA2CmB00QHMAUAiAlmTAXdAlAFBED0pABAO54AWASrFNAG6wBOERokuFA3hQAO7EAFtMEWAC5qdRszacANBXZMYbWesXZkAMQCuYYLkzgKAXwoBeCgAVREqfBq4GG1hwioCAbhI3D0VveHdYMFRUIQBDAE8kGIATAlsAPgEiCmyKHmYEJDR0EXFJWAcnMtd5TyUICghDYFhYJNb0VViEkGTiSwJ4YBjcYFoojlF2VJsM-iycvJgEKhj2SOLKqQrSlyCFTW8KCZB1JI6j9km+-xIdTT0jEzNwXwDyCgA9CgBRAA8hWCmVoUACMFFWyEMYgiuAgqgARoY+MgQHwAAzwVAAJgArDiACzEd7QTDw+BMLForH4+AlZwIJJhHxYkGqEE4giyACCYHB7Eh0LAfAAZicKAByFgxaCGWDi6gxepgVHCUQsTBtRkkd5Scq0XC4IQQaTkZB0Qxk0BiUgSYCiKDC3CkAAqcQBAGU7ZghE74Uh4aRYAA2YUxYBBoMxADsWNxMRBwBxAE4o0GqTjgwBmKNRmJYmL4+FooPwzPwgAcOJipAg7GApBJAYpVJpdKqjNhAGIADKZ7WUAD6Q+HQ-7uXAuHYitwwKCskcOwQdy8vm44AgfGXbCSC-ptm29PgW9gryIx53mwQ4Ui0XiiRS6UyOXHkCWiBQGDbW13VWPDSaLSaucXT3tcgzDKM4yXCc0yzPM2SLHArirOsX7lD+Lh-scpznNh1wBGQg4jsOY48JO06znQshgLAVAHmUq5wHwwCGBu4gYbA+xeAEeTMaxuDsZe+40XRHFRMesFPgs-GCYuXFsPux4BP0BEsWxYgcWEtARFEIE9A+MxSQh65voUn5CSJ9FSL4-7NK07SdHe+lgUMIxjKgeGPnMz6IcsKHmYuFCWWJqTYQ5FxXEQKkkJgwoUKgakCRpl7yeUACEdjGG0wrYK0qTedJ6kcalp7Pu8XzOrQkhHP8OgQOYvLVcqzHStAMR+gg8EUO8roAhKNFKPKtCKkFIC5K1DSYMgYDDIYOiYlimb4kmxBlZQTG5DJyVybUMhBbAShRUQQA

💻 Code

console.log("init")

// withResolvers
const { promise: withResolvers, resolve: resolvingFunction } = Promise.withResolvers();

withResolvers.then((payload) => {
    console.log("promise Promise.withResolvers suceeded", payload)
}).catch((error) => {
    console.warn("promise Promise.withResolvers errored", error)
});

resolvingFunction();
// ^ Expected 1 arguments, but got 0.(2554)
// lib.es2024.promise.d.ts(21, 15): An argument for 'value' was not provided.

// see https://github.com/microsoft/TypeScript/blob/e6fac66a7225a1c5976025e6377a2a4b06b3b85a/src/lib/es2024.promise.d.ts#L3

// ________

// contrasted with: Promise.resolve()
const resolvedPromise = Promise.resolve();
resolvedPromise.then((payload) => {
    console.log("promise Promise.resolve suceeded", payload)
}).catch((error) => {
    console.warn("promise Promise.resolve errored", error)
});

// ________

// contrasted with: new Promise()
let customPromiseResolve;
const customPromise = new Promise((resolve) => {
    customPromiseResolve = resolve;
});

customPromise.then((payload) => {
    console.log("promise new Promise() suceeded", payload)
}).catch((error) => {
    console.warn("promise new Promise() errored", error)
});

if (customPromiseResolve != undefined) {
    customPromiseResolve();
    // ^ This expression is not callable.
    // Type 'never' has no call signatures.(2349)
    // let customPromiseResolve: never
}

🙁 Actual behavior

Expected 1 arguments, but got 0.(2554)
lib.es2024.promise.d.ts(21, 15): An argument for 'value' was not provided.
const resolvingFunction: (value: unknown) => void

For some reason, it seems to expect unknown as a function parameter here thus requiring a function.

🙂 Expected behavior

As you can see when compared to Promise.resolve() or the manual pre-ES2024 implementation (that shows a different issue), they do not show the issue. And the important thing is: The code works as is (aka it shows all promises are properly called/resolved) in the browser, so the type-checking of TS did not catch a valid typing issue here, it's perfectly fine to call it like this.

I do not see why this should be different.

MDN does not mention this example but AFAIK you can use and there is nothing wrong with using the resolving Promise function (as e.g. returned from Promise.withResolvers) without any argument.

You can though "fix" the issue by explicitly stating Promise.withResolvers<void>(); must not accept any value aka the value the accept function returns/provides is really void. But why would you?
If I write it without any generic type, is not the default to assume void? Only if I were to provide a custom type, like with Promise.resolve<number>(1) I could specify it, but if none is provided, it also assumes void, does not it?

Additional information about the issue

Note the issue actually occurs in JS code (see downstream https://github.com/rugk/awesome-emoji-picker/pull/189/changes#diff-1402e6d2d65a300089b226dbfd589c0fc74ec00de6f618e3c1b6a4c1bf24c57f), and as type-casting there is really not simple, I would prefer not to do it. The "custom" implementation (aka with new Promise()) there worked, however.

Also, note the "custom" implementation before resulted in This expression is not callable. in the TS implementation. I did not see it in production, but this is also strange given this, again, is a valid JS code, too.
In JavaScript, the "old" "custom" implementation worked without special casting though.

#56483 introduced withResolvers.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Not a DefectThis behavior is one of several equally-correct options

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions