Closed
Description
I think that it should be special bottom type with the following properties:
- ( T | bottom ) = ( bottom | T ) = T — bottom is unit for type unions;
- expression of type bottom is assignable to any other type;
- bottom type could be used only as return type of the function (out-only);
- if function has return type bottom then all branches of the control flow either throw exceptions or return expression of type bottom;
- if all branches of the control flow either throw exceptions or return expression of type bottom and function has no explicit return type then bottom type inferred as the result type;
two functional types are not assignable to each other if exactly one of them has return type bottom(?);- bottom type can't be used as the actual type parameter for the generic type.
rationale
Let's consider the function that always throws:
function alwaysThrows() {
throw new Error("!");
}
and other function that uses it
function test(a: boolean) {
return a ? 123 : alwaysThrow();
}
We expect that test
should have type number
instead of ( number | void )
In more sophisticated example that involves Promise type declarations:
declare class Promise<T> {
catch<U>(
handler: (reason: any) => U | Promise<U>
): Promise<T | U>; // Note the union here (!)
then<U>(
fulfilled?: (result: T) => U | Promise<U>,
rejected?: (reason: any) => U | Promise<U>
): Promise<U>
}
We expect that
promiseOfString.catch(function(e) {
throw new BusinessError(e);
});
should have the type of Promise<string>
instead of Promise<string | void>
.
See petkaantonov/bluebird#589 (comment)
Possible explicit annotation that function always throws is using undefined as the type
function alwaysThrows(): undefined {
throw new Error("!");
}