Esto es por diseño (Voy a explicar por qué es un buen diseño en breve). La especificación dice (en la sección 3.6.3, abreviada para mayor claridad):
Un tipo S se puede asignar a un tipo T, y T es asignable a partir de S, si uno de los siguientes es verdadero ...
En este caso, estamos probando si () => stringes asignable a () => void. Así que, o stringtiene que ser asignable a void(no lo es), o voidtiene que ser void(es).
En efecto, la regla aquí es que se le permite tirar el valor de retorno , lo cual es consistente con la forma por ejemplo C ++ trata voiden la resolución de la plantilla.
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?
Cuando limitamos el tipo de changeser (widget) => void, lo estamos haciendo de manera que se puede pasar decrementWidgetHeightcomo segundo argumento a pesar de que tiene un valor de retorno, pero todavía asegurándose de que cuando escribimos el cuerpo de applyToManyWidgets, no utilizamos el accidente valor de retorno changeen cualquier lugar.
Tenga en cuenta que voidsigue siendo diferente de anyporque esto es inadmisible:
function f() { }
var x = f(); // Disallowed, f() is of type 'void'