-
Notifications
You must be signed in to change notification settings - Fork 12.8k
bug(esnext): add definition for promise.finally #20511
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
src/lib/esnext.promise.d.ts
Outdated
*/ | ||
finally<TResult = never>( | ||
onfinally?: (() => TResult | PromiseLike<TResult>) | undefined | null | ||
): Promise<T | TResult>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The result of the onfinally
callback is always ignored (unless it's a rejection). The way it works on the spec is pretty complicated, but it essentially wraps the onfinally
argument with a function that returns a Promise with the original Promise's state. It does allow for the onfinally
callback to throw, though, and that new exception would become the new rejection value, but it's not possible to alter the resolve value.
finally(onfinally?: (() => void) | undefined | null): Promise<T>
is the correct signature, unless we want to provide some way to support the result of Promise.reject
as a return value; but that can be done just as well by throw
ing inside the onfinally
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Kovensky thanks for the review.
I have one remark though, going with the return type void also means that the compiler won't complain if onfinally simply throws an error or returns any thing (since that is assignable to void). I guess that this is what we would like to have.
Also, it is indeed possible to have a Promise.reject (assignable to void) within finally
const generatePromise = (value)=> new Promise((resolve,reject)=>{
resolve(value);
});
generatePromise(13)
.finally(() => Promise.reject(10))
.then(data=>console.log(data))
.catch(data=>console.log(data))
I see however, that DefinitelyTyped definition for promise.prototype.finally is not going in the same direction as you proposed
interface Promise<T> {
finally<U>(onFinally?: () => U | PromiseLike<U>): Promise<T>;
}
I would like to have a confirmation first before making the change.
@Andy-MS I see that at some point you contributed to the file containing the definitions for promise.prototype.finally , could you please give us a recommendation on which definition to adopt
Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think void
is best. Accepting U
for an arbitrary value of U
just means accepting anything.
(I didn't contribute that definition; I just moved the file.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @Andy-MS @Kovensky
PR updated
* @param onfinally The callback to execute when the Promise is settled (fulfilled or rejected). | ||
* @returns A Promise for the completion of the callback. | ||
*/ | ||
finally(onfinally?: (() => void) | undefined | null): Promise<T> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would a return type of this
be appropriate here, or better to keep Promise<T>
?
It doesn't return the receiver itself; but the returned value can have the same type as the receiver...... if the receiver implements [Symbol.species]
. This is probably out of scope of what the type system can do...
This PR adds definition for Promise.prototype.finally
promise.finally is marked as esnext for the moment as it is not yet part of the finished proposals
Fixes #20411