2012-10-12 124 views
10

Si tengo una función como esta:¿Cómo puedo anotar tipos recursivos en TypeScript?

function say(message: string) { 
    alert(message); 
    return say; 
} 

tiene la propiedad interesante que puedo llamadas cadena a la misma:

say("Hello,")("how")("are")("you?"); 

El compilador generará una advertencia si paso un número en el primera llamada, pero me permitirá poner números en llamadas posteriores.

say("Hello")(1)(2)(3)(4) 

Lo anotación de tipo necesito para añadir a la función say para que el compilador genera advertencias cuando paso en los tipos válidos para las llamadas encadenadas?

Respuesta

18

Un tipo que hace referencia a sí mismo debe tener un nombre. Por ejemplo,

interface OmegaString { 
    (message: string): OmegaString; 
} 

entonces usted puede anotar say como OmegaString,

function say(message: string): OmegaString { 
    alert(message); 
    return say; 
} 

entonces el siguiente código de tipo de comprobación.

say("Hello,")("how")("are")("you?"); 

pero el siguiente no lo hará,

say("Hello")(1)(2)(3)(4) 
+0

Podría explicar en mayor detalle QUÉ debe tener un nombre? –

+2

@OldrichSvec Necesita un nombre para poder referirse a él, a menos que haya alguna palabra clave de tipo especial autorreferencial, que IMO no se usará con la frecuencia suficiente para que valga la pena agregarla. –

+0

@OldrichSvec Peter tiene toda la razón. Un tipo recursivo debe poder referirse a sí mismo. Darle un nombre le permite hacer referencia a sí mismo. – chuckj

0

método encadenables

Cuando se utiliza una clase en lugar de una función, se puede utilizar el tipo this para expresar el hecho de que un método devuelve la instancia a la que se llamó en (métodos de encadenamiento).

Sin this:

class StatusLogger { 
    log(message: string): StatusLogger { ... } 
} 
// this works 
new ErrorLogger().log('oh no!').log('something broke!').log(':-('); 

class PrettyLogger extends StatusLogger { 
    color(color: string): PrettyLogger { ... } 
} 
// this works 
new PrettyLogger().color('green').log('status: ').log('ok'); 
// this does not! 
new PrettyLogger().log('status: ').color('red').log('failed'); 

Con this:

class StatusLogger { 
    log(message: string): this { ... } 
} 
class PrettyLogger extends StatusLogger { 
    color(color: string): this { ... } 
} 
// this works now! 
new PrettyLogger().log('status:').color('green').log('works').log('yay'); 

función encadenables

Cuando una función es encadenables puede escribir con una interfaz:

function say(text: string): ChainableType { ... } 
interface ChainableType { 
    (text: string): ChainableType; 
} 
say('Hello')('World'); 

función de cadena con propiedades/métodos

Si una función tiene otras propiedades o métodos (como jQuery(str) vs jQuery.data(el)), puede escribir la función como una interfaz:

interface SayWithVolume { 
    (message: string): this; 
    loud(): this; 
    quiet(): this; 
} 

const say: SayWithVolume = ((message: string) => { ... }) as SayWithVolume; 
say.loud =() => { ... }; 
say.quiet =() => { ... }; 

say('hello').quiet()('can you hear me?').loud()('hello from the other side'); 
Cuestiones relacionadas