Fix inferred types for targetted error handlers

The typings for targetted catch statements don't infer properly with Error constructors, for example with `.catch(SomeErrorSubtype, (e) => /*...*/)`, `e` is inferred to be the constructor of SomeErrorSubtype, not an instance of SomeErrorSubtype, so this must be explicitly typed as `.catch(SomeErrorSubtype, (e: SomeErrorSubtype) => /*...*/)` for the typings to be accurate.  The root causes is that it is erroneously falling into the wrong overload, the overload that accepts arbitrary objects as the first argument to .catch.  This fix requires loosening the restriction that SomeErrorSubtype must be a subtype of Error, but otherwise preserves existing behavior.

Also, makes a utility type to reduce some of the boilerplate.
This commit is contained in:
Retsam 2017-12-13 14:02:42 -05:00
parent 79258c041a
commit d73f413fb6

View File

@ -35,6 +35,8 @@
* THE SOFTWARE.
*/
type CatchFilter<E> = (new (...args: any[]) => E) | ((error: E) => boolean) | (object & E);
declare class Bluebird<R> implements PromiseLike<R>, Bluebird.Inspection<R> {
/**
* Create a new promise. The passed in function will receive functions `resolve` and `reject` as its arguments which can be called to seal the fate of the created promise.
@ -77,128 +79,69 @@ declare class Bluebird<R> implements PromiseLike<R>, Bluebird.Inspection<R> {
*
* Alias `.caught();` for compatibility with earlier ECMAScript version.
*/
catch<E1 extends Error, E2 extends Error, E3 extends Error, E4 extends Error, E5 extends Error>(
filter1: (new (...args: any[]) => E1),
filter2: (new (...args: any[]) => E2),
filter3: (new (...args: any[]) => E3),
filter4: (new (...args: any[]) => E4),
filter5: (new (...args: any[]) => E5),
onReject: (error: E1 | E2 | E3 | E4 | E5) => R | PromiseLike<R>,
): Bluebird<R>;
catch<E1, E2, E3, E4, E5>(
filter1: ((error: E1) => boolean) | (E1 & object),
filter2: ((error: E2) => boolean) | (E2 & object),
filter3: ((error: E3) => boolean) | (E3 & object),
filter4: ((error: E4) => boolean) | (E4 & object),
filter5: ((error: E5) => boolean) | (E5 & object),
filter1: CatchFilter<E1>,
filter2: CatchFilter<E2>,
filter3: CatchFilter<E3>,
filter4: CatchFilter<E4>,
filter5: CatchFilter<E5>,
onReject: (error: E1 | E2 | E3 | E4 | E5) => R | PromiseLike<R>,
): Bluebird<R>;
catch<U, E1 extends Error, E2 extends Error, E3 extends Error, E4 extends Error, E5 extends Error>(
filter1: (new (...args: any[]) => E1),
filter2: (new (...args: any[]) => E2),
filter3: (new (...args: any[]) => E3),
filter4: (new (...args: any[]) => E4),
filter5: (new (...args: any[]) => E5),
onReject: (error: E1 | E2 | E3 | E4 | E5) => U | PromiseLike<U>,
): Bluebird<U | R>;
catch<U, E1, E2, E3, E4, E5>(
filter1: ((error: E1) => boolean) | (E1 & object),
filter2: ((error: E2) => boolean) | (E2 & object),
filter3: ((error: E3) => boolean) | (E3 & object),
filter4: ((error: E4) => boolean) | (E4 & object),
filter5: ((error: E5) => boolean) | (E5 & object),
filter1: CatchFilter<E1>,
filter2: CatchFilter<E2>,
filter3: CatchFilter<E3>,
filter4: CatchFilter<E4>,
filter5: CatchFilter<E5>,
onReject: (error: E1 | E2 | E3 | E4 | E5) => U | PromiseLike<U>,
): Bluebird<U | R>;
catch<E1 extends Error, E2 extends Error, E3 extends Error, E4 extends Error>(
filter1: (new (...args: any[]) => E1),
filter2: (new (...args: any[]) => E2),
filter3: (new (...args: any[]) => E3),
filter4: (new (...args: any[]) => E4),
onReject: (error: E1 | E2 | E3 | E4) => R | PromiseLike<R>,
): Bluebird<R>;
catch<E1, E2, E3, E4>(
filter1: ((error: E1) => boolean) | (E1 & object),
filter2: ((error: E2) => boolean) | (E2 & object),
filter3: ((error: E3) => boolean) | (E3 & object),
filter4: ((error: E4) => boolean) | (E4 & object),
filter1: CatchFilter<E1>,
filter2: CatchFilter<E2>,
filter3: CatchFilter<E3>,
filter4: CatchFilter<E4>,
onReject: (error: E1 | E2 | E3 | E4) => R | PromiseLike<R>,
): Bluebird<R>;
catch<U, E1 extends Error, E2 extends Error, E3 extends Error, E4 extends Error>(
filter1: (new (...args: any[]) => E1),
filter2: (new (...args: any[]) => E2),
filter3: (new (...args: any[]) => E3),
filter4: (new (...args: any[]) => E4),
onReject: (error: E1 | E2 | E3 | E4) => U | PromiseLike<U>,
): Bluebird<U | R>;
catch<U, E1, E2, E3, E4>(
filter1: ((error: E1) => boolean) | (E1 & object),
filter2: ((error: E2) => boolean) | (E2 & object),
filter3: ((error: E3) => boolean) | (E3 & object),
filter4: ((error: E4) => boolean) | (E4 & object),
filter1: CatchFilter<E1>,
filter2: CatchFilter<E2>,
filter3: CatchFilter<E3>,
filter4: CatchFilter<E4>,
onReject: (error: E1 | E2 | E3 | E4) => U | PromiseLike<U>,
): Bluebird<U | R>;
catch<E1 extends Error, E2 extends Error, E3 extends Error>(
filter1: (new (...args: any[]) => E1),
filter2: (new (...args: any[]) => E2),
filter3: (new (...args: any[]) => E3),
onReject: (error: E1 | E2 | E3) => R | PromiseLike<R>,
): Bluebird<R>;
catch<E1, E2, E3>(
filter1: ((error: E1) => boolean) | (E1 & object),
filter2: ((error: E2) => boolean) | (E2 & object),
filter3: ((error: E3) => boolean) | (E3 & object),
filter1: CatchFilter<E1>,
filter2: CatchFilter<E2>,
filter3: CatchFilter<E3>,
onReject: (error: E1 | E2 | E3) => R | PromiseLike<R>,
): Bluebird<R>;
catch<U, E1 extends Error, E2 extends Error, E3 extends Error>(
filter1: (new (...args: any[]) => E1),
filter2: (new (...args: any[]) => E2),
filter3: (new (...args: any[]) => E3),
onReject: (error: E1 | E2 | E3) => U | PromiseLike<U>,
): Bluebird<U | R>;
catch<U, E1, E2, E3>(
filter1: ((error: E1) => boolean) | (E1 & object),
filter2: ((error: E2) => boolean) | (E2 & object),
filter3: ((error: E3) => boolean) | (E3 & object),
filter1: CatchFilter<E1>,
filter2: CatchFilter<E2>,
filter3: CatchFilter<E3>,
onReject: (error: E1 | E2 | E3) => U | PromiseLike<U>,
): Bluebird<U | R>;
catch<E1 extends Error, E2 extends Error>(
filter1: (new (...args: any[]) => E1),
filter2: (new (...args: any[]) => E2),
onReject: (error: E1 | E2) => R | PromiseLike<R>,
): Bluebird<R>;
catch<E1, E2>(
filter1: ((error: E1) => boolean) | (E1 & object),
filter2: ((error: E2) => boolean) | (E2 & object),
filter1: CatchFilter<E1>,
filter2: CatchFilter<E2>,
onReject: (error: E1 | E2) => R | PromiseLike<R>,
): Bluebird<R>;
catch<U, E1 extends Error, E2 extends Error>(
filter1: (new (...args: any[]) => E1),
filter2: (new (...args: any[]) => E2),
onReject: (error: E1 | E2) => U | PromiseLike<U>,
): Bluebird<U | R>;
catch<U, E1, E2>(
filter1: ((error: E1) => boolean) | (E1 & object),
filter2: ((error: E2) => boolean) | (E2 & object),
filter1: CatchFilter<E1>,
filter2: CatchFilter<E2>,
onReject: (error: E1 | E2) => U | PromiseLike<U>,
): Bluebird<U | R>;
catch<E1 extends Error>(
filter1: (new (...args: any[]) => E1),
onReject: (error: E1) => R | PromiseLike<R>,
): Bluebird<R>;
catch<E1>(
filter1: ((error: E1) => boolean) | (E1 & object),
filter1: CatchFilter<E1>,
onReject: (error: E1) => R | PromiseLike<R>,
): Bluebird<R>;
catch<U, E1 extends Error>(
filter1: (new (...args: any[]) => E1),
onReject: (error: E1) => U | PromiseLike<U>,
): Bluebird<U | R>;
catch<U, E1>(
filter1: ((error: E1) => boolean) | (E1 & object),
filter1: CatchFilter<E1>,
onReject: (error: E1) => U | PromiseLike<U>,
): Bluebird<U | R>;