¿Qué hace 'declarar' en 'export declare Class Actions'?

Respuestas:

212

encontré lo que estaba buscando:

Declarar contra var

varcrea una nueva variable. declarese usa para decirle a TypeScript que la variable se ha creado en otro lugar. Si usa declare, no se agrega nada al JavaScript que se genera; es simplemente una pista para el compilador.

Por ejemplo, si usa un script externo que define var externalModule, usaría declare var externalModulepara insinuar el compilador de TypeScript que externalModuleya se ha configurado

born2net
fuente
Tengo un escenario similar con un JS externo que define una variable externalModuleentre otras. ¿Cuál podría ser la razón por la cual externalModuleno está definida en tiempo de ejecución pero algunas de las otras variables no?
Alejandro González
94

Para comprender esto, primero debe comprender la palabra clave "declarar".

Aquí hay una buena explicación del blog de Gil Fink :

La palabra clave de declaración TypeScript se utiliza para declarar variables que pueden no haberse originado en un archivo TypeScript.

Por ejemplo, imaginemos que tenemos una biblioteca llamada myLibrary que no tiene un archivo de declaración TypeScript y un espacio de nombres llamado myLibrary en el espacio de nombres global. Si desea usar esa biblioteca en su código TypeScript, puede usar el siguiente código:

declare var myLibrary;

El tipo que el tiempo de ejecución de TypeScript dará a la variable myLibrary es cualquier tipo. El problema aquí es que no tendrá Intellisense para esa variable en tiempo de diseño, pero podrá usar la biblioteca en su código. Otra opción para tener el mismo comportamiento sin usar la palabra clave declare es simplemente usar una variable con cualquier tipo:

var myLibrary: any;

Ambos ejemplos de código darán como resultado la misma salida de JavaScript, pero el ejemplo de declaración es más legible y expresa una declaración ambiental.


Entonces, después de comprender la palabra clave "declarar", regrese a donde encuentre el

export declare class Action{
...
}

La implementación real de la clase probablemente se encuentre en otro lugar, tal vez un archivo .js.

Terrence
fuente
2
"Ambos ejemplos de código darán como resultado la misma salida de JavaScript", eso no es cierto: declare var myLibraryse trasladará a la nada: typescriptlang.org/play/#code/…
apollo el
38

declare en mecanografiado:

La declarepalabra clave en mecanografiado es útil para decirle al compilador mecanografiado que una declaración está definida en otro lugar (en algún lugar escrito en un archivo javascript externo o parte del entorno de tiempo de ejecución).

Digamos que tenemos una variable llamada foo declarada en otro lugar. Cuando intentamos hacer referencia a la variable, el compilador mecanografiado arrojará un error:

foo = 'random'; // Error: 'foo' is not defined

Podemos solucionar este problema usando la declarepalabra clave:

declare var foo: string;
foo = 'random';  // no error anymore

Esto tiene las siguientes consecuencias:

  • Cuando en foorealidad no se declara en ningún otro lugar, e intentamos usar la variable, puede ocurrir un error de tiempo de ejecución. Por lo tanto, solo use la declarepalabra clave cuando sepa que la variable está disponible en este momento.
  • Debido a que conocemos los tipos, (potencialmente) tenemos acceso a nuestro IDE Intellisense .
  • Debido a que conocemos los tipos, el compilador mecanografiado puede verificar los tipos en el momento de la compilación y puede advertirnos si estamos usando los tipos incorrectos en ciertos escenarios.
Willem van der Veen
fuente
18

La palabra clave declarar en este caso específico:

export declare class Actions {
    ...
}

... aparentemente es inútil y creo que TypeScript debería considerar hacer esto un error (no sé si hay una razón oculta). Si declara una clase, nunca necesitará importarla. Si exporta una clase esperando que alguien la importe, no necesita declararla. Y debido a que está declarando esta clase, por definición, esta clase debería ser utilizable sin la necesidad de importarla. Pero esto no es cierto cuando exporta declarar una clase. Usted necesita importarlo a utilizar.

TL; DR

export declare class Actions {
    ...
}

es lo mismo que

declare class Actions {
    ...
}
André Pena
fuente
No creo que sean iguales, el primero debe usarse import, el segundo no
Ian Zhong
10

declare - sin palabras clave de importación o exportación - define archivos de declaración seleccionados automáticamente por TypeScript, que es una característica útil para agregar escritura a módulos heredados (paquetes instalados npm sin definiciones de TypeScript).

import/ exportes la forma correcta de usar módulos, y todo necesita ser importado manualmente (y me parece un poco tedioso), ya sea lógica, o bien son definiciones.

Como un caso de uso práctico, le export declarepermite evitar exportar todos los subelementos, por ejemplo:

export declare namespace Redux {
    namespace Store {
        interface Definition { ... }
    }
}

Que puede ser más fácil de leer que:

export namespace Redux {
    export namespace Store {
        export interface Definition { ... }
    }
}

La importación externa es la misma en ambos casos (p. Ej. import { Redux } from 'definitions/redux'; . ), Lo que no sé si es una buena práctica o no, ¡pero lo encuentro ordenado! ^^

Es importante tener en cuenta que la adición de una importo exportde su archivo promoverá que sea un módulo, por lo que el declarealcance no será a nivel mundial más.

PS, hay un error ( problema 16671 ): si usa const enumen su declaración (lo hago para el tipo de acciones redux) y especificó el transpileOnlyindicador (el paquete create-react-app-typescript lo hace, por eso lo sé), el ¡enumeración no estará en línea! Puede correr en él, puede que no, ¡pero es útil saberlo de antemano!

pierpytom
fuente
Los espacios de nombres dentro de los módulos noexport namespace son una buena idea y agregan espacios de nombres innecesarios . Al respecto export declare, eche un vistazo a la respuesta de André Pena.
Ford04