TypeScript: void return type converted to any type?
This is by design (I'll explain why it's good design shortly). The spec says (in section 3.6.3, abridged for clarity):
A type S is assignable to a type T, and T is assignable from S, if one of the following is true...
S and T are object types and, for each member M in T, one of the following is true:
M is a call, construct or index signature and S contains a call, construct or index signature N where
- the result type of M is Void, or the result type of N is assignable to that of M.
In this case, we're testing if () => string
is assignable to () => void
. So either string
has to be assignable to void
(it isn't), or void
has to be void
(it is).
In effect, the rule here is you are allowed to throw away the return value, which is consistent with how e.g. C++ treats void
in template resolution.
function decrementWidgetHeight(w: Widget): number {
// ... returns the new height of the widget
}
function applyToManyWidgets(w: Widget[], change: (x: Widget) => void): void {
// for each widget in the array, apply 'change' to it
}
// Later...
applyToManyWidgets(widgetsToShorten, decrementWidgetHeight); // Should be allowed?
When we constrain the type of change
to be (widget) => void
, we're making it so that you can pass decrementWidgetHeight
as the second argument even though it has a return value, but still making sure that when we write the body of applyToManyWidgets
, we don't accidentally use the return value of change
anywhere.
Note that void
is still different than any
because this is unallowed:
function f() { }
var x = f(); // Disallowed, f() is of type 'void'