Skip to content

Incorrect return types for Promise#catch and 0- and 2- arg forms of Promise#then #9193

Description

@jeffreymorlan
Expression (p: Promise) Correct type Current type
p.then() Promise Promise<{}>
p.then(b => 1) Promise Promise
p.then(b => 1, e => 'error') Promise<number string>
p.then(b => 1, e => {}) Promise<number void>
p.then(b => 1, e => {throw Error()}) Promise Promise
p.then(b => 1, e => Promise.reject(Error())) Promise Promise
p.catch(e => 'error') Promise<boolean string>
p.catch(e => {}) Promise<boolean void>
p.catch(e => {throw Error()}) Promise Promise
p.catch(e => Promise.reject(Error())) Promise Promise

Using overloading and the new never type, PromiseLike/Promise could be typed to handle all these cases correctly:

interface PromiseLike<T> {
    then(): PromiseLike<T>;
    then<R1>(onfulfilled: (value: T) => R1 | PromiseLike<R1>): PromiseLike<R1>;
    then<R1, R2>(onfulfilled: (value: T) => R1 | PromiseLike<R1>,
                 onrejected: (reason: any) => R2 | PromiseLike<R2>): PromiseLike<R1 | R2>;
}

interface Promise<T> {
    then(): Promise<T>;
    then<R1>(onfulfilled: (value: T) => R1 | PromiseLike<R1>): Promise<R1>;
    then<R1, R2>(onfulfilled: (value: T) => R1 | PromiseLike<R1>,
                 onrejected: (reason: any) => R2 | PromiseLike<R2>): Promise<R1 | R2>;
    catch<R2>(onrejected: (reason: any) => R2 | PromiseLike<R2>): Promise<T | R2>;
}

declare var Promise: {
    reject(reason: any): Promise<never>; // Returned promise is never fulfilled
};

Metadata

Metadata

Assignees

No one assigned

    Labels

    FixedA PR has been merged for this issueSuggestionAn idea for TypeScript

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions