Skip to content

v1.1.0.0 issues TS2345 if Q.Promise.then.onReject throws without a return #947

@psnider

Description

@psnider

I thought that TypeScript ignores the requirement to return a value if an exception is thrown, as in the following code that compiles fine:

function n() : number {
    throw 'help';
}

But when using a Q.Promise with a specific type, not any, it seems that the compiler wants to resolve the return type of the onReject function, even though the most common usage is to throw an exception. The following code doesn't compile with tsc --module commonjs t.ts:

/// <reference path='decl/import/Q.d.ts' />
import Q                                = require('q');
interface A {a: number;}
declare function get() : Q.Promise<A>;   //  compiles if type is relaxed to any
function wrappedGet() : Q.Promise<any> {
    return get().then(
        (result) => {
            console.log('got result');
            return result;
        },
        (reason) => {
            console.log('reason=' + reason);
            throw reason;
            // return reason;    // compiles if this line is uncommented
        }
    );    
}

and issues the error:

t.ts(11,9): error TS2345: Argument of type '(reason: any) => void' is not assignable to parameter of type '(reason: any) => {}'.

Now I'm faced with adding unnecessary return statements to each of my then.onReject handlers, wherever I've tightened up the return type of the promise.

I don't think I should have to do this.
Am I doing something wrong?

For reference, a fragment of the Q declarations I'm using is:

declare module Q {
    interface IPromise<T> {
        then<U>(onFulfill: (value: T) => IPromise<U>, onReject?: (reason: any) => IPromise<U>): IPromise<U>;
        then<U>(onFulfill: (value: T) => IPromise<U>, onReject?: (reason: any) => U): IPromise<U>;
        then<U>(onFulfill: (value: T) => U, onReject?: (reason: any) => IPromise<U>): IPromise<U>;
        then<U>(onFulfill: (value: T) => U, onReject?: (reason: any) => U): IPromise<U>;
    }

    interface Promise<T> {
        then<U>(onFulfill: (value: T) => IPromise<U>, onReject?: (reason: any) => IPromise<U>, onProgress?: Function): Promise<U>;
        then<U>(onFulfill: (value: T) => IPromise<U>, onReject?: (reason: any) => U, onProgress?: Function): Promise<U>;
        then<U>(onFulfill: (value: T) => U, onReject?: (reason: any) => IPromise<U>, onProgress?: Function): Promise<U>;
        then<U>(onFulfill: (value: T) => U, onReject?: (reason: any) => U, onProgress?: Function): Promise<U>;

Metadata

Metadata

Assignees

No one assigned

    Labels

    By DesignDeprecated - use "Working as Intended" or "Design Limitation" instead

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions