-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
More strong Promise<T> in lib.es6.d.ts #5413
Comments
This is another good use-case for implementing #2175. interface Promise<T, U = Error> {
// ...
} |
You didn't update the types of PromiseLike and Promise returned from then and catch. If you had, you'd see the error type becomes larger and larger, since all promises in a chain contribute to the error type (unlike the result type where only the last promise contributes to it). Consider: // A promise that resolves to string value or rejects with number value
var promise: Promise<string, number>;
// A promise that uses previous promise to resolve to string value or fail with Error value,
// and lets failure of previous promise fall-through.
var promise2 = promise.then(result => {
if (result.length === 0) {
throw new Error("");
}
return result;
});
So at a minimum (i.e., the best you can do with current TS syntax) you'd need to do this: then<TResult, TError>(onfulfilled?: (value: T) => TResult, onrejected?: (reason: U) => TResult | PromiseLike<TResult>): Promise<TResult, U | TError>;
// Explicitly need to pass in specialization of TError = Error since it is unbound otherwise.
// Even if neither callback throws a different type than U (or throws at all), this will still be needed.
var promise2 = promise.then<string, Error>(...); To have TS bind TError implicitly, you'd need some kind of then<TResult, TError>(onfulfilled?: (value: T) => TResult throws TError, onrejected?: (reason: U) => TResult | PromiseLike<TResult> throws TError): Promise<TResult, U | TError>; and then require TS to be able to consider This then basically becomes checked exceptions which bring all of their associated problems (like being unable to be used with higher-ordered functions). |
Surely we can add the error generic and it will default to For context, I am using the browser’s fetch('foo').catch(e => {
e.message // string
})
I see, however TypeScript would know to append |
Workaround for /**
* Represents the completion of an asynchronous operation
*/
interface PromiseWithError<T, U> extends 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: U) => TResult2 | PromiseLike<TResult2>) | undefined | null,
): PromiseWithError<TResult1 | TResult2, U>;
/**
* 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: U) => TResult | PromiseLike<TResult>) | undefined | null,
): PromiseWithError<T | TResult, U>;
}
const promise: PromiseWithError<any, Error> = fetch('foo');
const promise2 = promise.catch(e => e.message);
const promise3: Promise<any> = promise2;
promise3;
const fetchPromiseWithError = (
url: string,
init?: fetch.RequestInit,
): PromiseWithError<fetch.Response, Error> => fetch(url, init);
fetchPromiseWithError('foo').catch(e => e.message); |
This should be consistent with synchronous exceptions, i.e. this should be done if and only if #13219 gets implemented |
I agree the ideal solution would be to have typed exceptions and then being able to correctly type Promises... but seeing that it may take a looooong time to have typed exceptions, I created a library that works likes promises but with a subtle difference that allows me to have typed errors and a pretty good error inference. Been using it on production for more than 6months and I'm really happy with the results. The whole problem arises because we can't forbid a function from throwing, and we cant know the type that it's thrown, so what I did is favour the idiomatic way of returning an error, which is returning a rejected "Promise" and if for some reason a function throws, i put the error inside an UnknownError class, with an unknown property. Here's the library https://github.com/ts-task/task and here is a video explain in it with more detail https://www.youtube.com/watch?v=T7O1T1wmw00 |
I think it would be good to be able to define the type of error in
Promise
type. I suggest promise type to be something like this:Or at least have a
Promise<T, U>
type which extendsPromise<T>
.The text was updated successfully, but these errors were encountered: