Reputation: 650
I do't quite understand Promise
definition of TypeScript
as below:
/**
* Represents the completion of an asynchronous operation
*/
interface Promise<T> {
/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onfulfilled The callback to execute when the Promise is resolved.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of which ever callback is executed.
*/
then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
/**
* Attaches a callback for only the rejection of the Promise.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of the callback.
*/
catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult>;
}
I think then<TResult1 = T, TResult2 = never>
means then
has two generic types, which are TResult1
and TResult2
. And TResult1
will be T
if not specified.
But it turns out that TResult1
will change according to the return type
of onfulfilled
. See demo :
interface Result {
status: number;
message: string;
}
function foo() {
return new Promise<Result>(function (resolve, reject) {
resolve({
status: 0,
message: 'ok',
});
});
}
// here fulfilled1's type is: (local function) fulfilled(out: Result): number
foo().then(function fulfilled1(out) {
if (Math.random() > 0.5) {
return 1;
}
});
// here fullfilled2's type is: (local function) fulfilled2(out: Result): string
foo().then(function fulfilled2(out) {
if (Math.random() > 0.5) {
return 'hello';
}
});
both fulfilled1
and fulfilled2
matches then<TResult1 = T, TResult2 = never>
. But since I do not sepecify then
generic types, I thought TResult1
would be Result
in the above code, while in face TResul1
becomes number
and string
in these case.
Maybe I take something wrong with TypeScript
generic
.
Any ideas are appreciated.
Upvotes: 1
Views: 2292
Reputation: 249506
The default will be used when no inference can be made for TResult1
. In this case an inference can be made based on the function you pass in. Since both parameters to then
are marked as optional, this would be a valid call, and will trigger the default:
foo().then() // returns a promise with TResult1
Or a more useful example, passing in just the second argument, again TResult1
uses the default.
var r = foo().then(undefined, r => "ERR"); // Promise<string | Result>
If you do pass in a function, that function can change the type of the returned promise, and I think this is the way most people use promises, perform an async call, process the result, return something else to as the next result.
Upvotes: 1