O que 'declare' faz em 'export declare Actions Actions'?


Respostas:


212

encontrou o que estava procurando:

Declarar vs. var

varcria uma nova variável. declareé usado para informar ao TypeScript que a variável foi criada em outro lugar. Se você usar declare, nada será adicionado ao JavaScript gerado - é simplesmente uma dica para o compilador.

Por exemplo, se você usa um script externo que define var externalModule, você declare var externalModulepode sugerir ao compilador TypeScript que externalModulejá foi configurado


Eu tenho um cenário semelhante com um JS externo que define uma variável externalModuleentre outros. Qual poderia ser o motivo pelo qual externalModuleé indefinido em tempo de execução, mas algumas das outras variáveis ​​não?
Alejandro González

94

Para entender isso, você deve primeiro entender a palavra-chave "declare".

Aqui está uma boa explicação do Blog de Gil Fink :

A palavra-chave declarar TypeScript é usada para declarar variáveis ​​que podem não ter se originado de um arquivo TypeScript.

Por exemplo, vamos imaginar que temos uma biblioteca chamada myLibrary que não possui um arquivo de declaração TypeScript e um namespace chamado myLibrary no namespace global. Se você deseja usar essa biblioteca no seu código TypeScript, pode usar o seguinte código:

declare var myLibrary;

O tipo que o tempo de execução TypeScript dará à variável myLibrary é qualquer tipo. O problema aqui é que você não terá o Intellisense para essa variável em tempo de design, mas poderá usar a biblioteca em seu código. Outra opção para ter o mesmo comportamento sem usar a palavra-chave declare é apenas usar uma variável com o tipo any:

var myLibrary: any;

Os dois exemplos de código resultarão na mesma saída JavaScript, mas o exemplo de declaração é mais legível e expressa uma declaração de ambiente.


Então, depois de entender a palavra-chave "declarar", volte para onde quer que encontre o

export declare class Action{
...
}

A implementação real da classe provavelmente está em outro lugar - talvez um arquivo .js.


2
"Ambos os exemplos de código resultarão na mesma saída JavaScript", isso não é verdade: declare var myLibraryserá transpilado para nada: typescriptlang.org/play/#code/…
apollo

38

declare em texto datilografado:

A declarepalavra-chave em texto datilografado é útil para informar ao compilador texto datilografado que uma declaração é definida em outro lugar (em algum lugar escrito em um arquivo javascript externo ou em parte do ambiente de tempo de execução).

Digamos que temos uma variável chamada foo declarada em outro lugar. Quando tentamos fazer referência à variável, o compilador de texto datilografado gera um erro:

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

Podemos corrigir esse problema usando a declarepalavra-chave:

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

Isso tem as seguintes consequências:

  • Quando foona verdade não é declarado em nenhum outro lugar, e tentamos usar a variável, um erro de tempo de execução pode ocorrer. Portanto, use apenas a declarepalavra - chave quando souber que a variável está disponível neste momento.
  • Como conhecemos os tipos, (potencialmente) obtemos acesso ao nosso IDE Intellisense .
  • Como conhecemos os tipos, o compilador de texto datilografado pode verificar os tipos em tempo de compilação e nos avisar se estivermos usando os tipos errados em determinados cenários.

18

A palavra-chave declare neste caso específico:

export declare class Actions {
    ...
}

... é aparentemente inútil e acho que o TypeScript deve considerar cometer um erro (não sei se há um motivo oculto). Se você declarar uma classe, nunca precisará importá-la. Se você exportar uma classe esperando que alguém a importe, não será necessário declará-la. E como você está declarando essa classe, por definição, essa classe deve ser utilizável sem a necessidade de importá-la. Mas isso não é verdade quando você exporta declarar uma classe. Você precisa importá-lo para usar.

TL; DR

export declare class Actions {
    ...
}

é o mesmo que

declare class Actions {
    ...
}

Eu não acho que eles são iguais, o primeiro precisa usar import, o segundo não
Ian Zhong

10

declare - sem nenhuma palavra-chave de importação ou exportação - define os arquivos de declaração escolhidos automaticamente pelo TypeScript, que é um recurso útil para adicionar digitação aos módulos herdados (pacotes instalados npm sem definições do TypeScript).

import/ exporté a maneira correta de usar módulos e tudo precisa ser importado manualmente (e acho um pouco entediante), seja lógica, seja definições.

Como um caso de uso prático, export declareevita-se exportar todos os subelementos, por exemplo:

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

O que pode ser mais fácil de ler do que:

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

A importação externa é a mesma nos dois casos (por exemplo import { Redux } from 'definitions/redux';), que eu não sei se é uma boa prática ou não, mas acho tudo arrumado! ^^

É importante ter em mente que a adição de um arquivo importou exportao seu arquivo o promoverá como um módulo; portanto, o declareescopo não estará mais em nível global.

PS, existe um erro ( problema 16671 ): se você usa const enumna sua declaração (eu faço isso para o tipo de ações redux) e você especificou a transpileOnlyflag (o pacote create-react-app-typescript faz, é por isso que eu sei), o enum não será incorporado! Você pode correr nele, pode não, mas é útil saber de antemão!


Os espaços para nome dentro dos módulos ala nãoexport namespace são uma boa idéia e adicionam espaço para nome desnecessário . A respeito export declare, dê uma olhada na resposta de André Pena.
Ford04 29/09/19
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.