2012-10-06 50 views
17

Me parece que no es capaz de comprender por qué el siguiente código no plantea error:TypeScript: tipo de devolución vacía convertida a cualquier tipo?

var rg: {(): void;}[] = []; 
rg.push(function():string {return "";}) 

digo claramente que el tipo debe ser un conjunto de funciones que devuelven void, sin embargo empujo existe una función que devuelve a string y, sin embargo, el compilador no se queja. Si cambio de la definición de rg a

var rg: {():number;}[] = []; 

El compilador comienza a quejarse.

¿Es esto un error o cómo se supone que funciona el retorno de nulo (es decir, todo vale si se usa void, básicamente haciendo lo mismo que el tipo de retorno any)?

+0

he [interpuso una cuestión] (http://typescript.codeplex.com/workitem/139). –

Respuesta

17

Esto es por diseño (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):

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.

En este caso, estamos probando si es asignable a () => string() => void. Entonces, o bien string tiene que ser asignable a void (no lo es), o void tiene que ser void (es).


De hecho, la regla aquí es se le permite tirar el valor de retorno, lo cual es consistente con la forma, por ejemplo, C++ trata void en resolución de 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 change ser (widget) => void, lo estamos haciendo para que pueda pasar decrementWidgetHeight como segundo argumento a pesar de que tiene un valor de retorno, pero sigue asegurándose de que cuando escriba el cuerpo de applyToManyWidgets, no utilizamos accidentalmente el valor de retorno de change en ninguna parte.

Tenga en cuenta que void sigue siendo diferente de any porque esto es inadmisible:

function f() { } 
var x = f(); // Disallowed, f() is of type 'void' 
+0

+1 - puede probar esto usando: 'var rg: {(): void;} [] = []; rg.push (function(): string {return "";}) var x = rg [0](); 'en el área de juegos de TypeScript para ver el comportamiento en acción. Cambie 'void' a' string' y permitirá que se use el valor de retorno. – Fenton

+0

Está bien, tiene sentido, pero es un poco intuitivo, es decir, permite agregar una función que no coincide con el tipo, incluso si es vacío en la definición. –

+1

La especificación también dice "el vacío solo está relacionado con los tipos indefinido, nulo y cualquiera", por lo que no estoy seguro de que la especificación sea consistente. Definitivamente inesperado. – Roly

0

Parece un error. Debería abrir un new work item para el número

+0

[Hizo eso] (https://typescript.codeplex.com/workitem/1734), pero dado el comentario anterior, supongo que esto es así. No encontrar mucho uso de genéricos en TS hasta ahora ... – Roly

Cuestiones relacionadas