Co robi „deklaruj” w „eksporcie deklaruj akcje klasowe”?


Odpowiedzi:


212

znalazłem to, czego szukałem:

Deklaracja vs. var

vartworzy nową zmienną. declaresłuży do informowania TypeScript, że zmienna została utworzona gdzie indziej. Jeśli używasz declare, nic nie jest dodawane do generowanego JavaScript - to po prostu wskazówka dla kompilatora.

Na przykład, jeśli użyjesz zewnętrznego skryptu, który definiuje var externalModule, możesz declare var externalModulewskazać kompilator TypeScript, który externalModulezostał już skonfigurowany


Mam podobny scenariusz z zewnętrznym JS definiującym externalModulemiędzy innymi zmienną . Jaki może być powód, dla którego externalModulew środowisku wykonawczym jest niezdefiniowany, ale niektóre inne zmienne nie?
Alejandro González

94

Aby to zrozumieć, musisz najpierw zrozumieć słowo kluczowe „deklaruj”.

Oto dobre wyjaśnienie z bloga Gila Finka :

Słowo kluczowe deklarujące TypeScript służy do deklarowania zmiennych, które mogły nie pochodzić z pliku TypeScript.

Na przykład, wyobraźmy sobie, że mamy bibliotekę o nazwie myLibrary, która nie ma pliku deklaracji TypeScript i mamy przestrzeń nazw o nazwie myLibrary w globalnej przestrzeni nazw. Jeśli chcesz użyć tej biblioteki w kodzie TypeScript, możesz użyć następującego kodu:

declare var myLibrary;

Typem, który środowisko wykonawcze TypeScript nada zmiennej myLibrary, jest dowolny typ. Problem polega na tym, że nie będziesz mieć Intellisense dla tej zmiennej w czasie projektowania, ale będziesz mógł używać biblioteki w swoim kodzie. Inną opcją zachowania tego samego zachowania bez użycia słowa kluczowego deklaruj jest po prostu użycie zmiennej dowolnego typu:

var myLibrary: any;

Oba przykłady kodu skutkują tym samym wynikiem JavaScript, ale przykład deklaracji jest bardziej czytelny i wyraża deklarację otoczenia.


Po zrozumieniu słowa kluczowego „deklaruj” wróć do dowolnego miejsca

export declare class Action{
...
}

Prawdziwa implementacja klasy prawdopodobnie znajduje się gdzie indziej - może w pliku .js.


2
„Oba przykłady kodu spowoduje tym samym wyjściem Javascript”, to nie jest prawdziwe: declare var myLibrarybędzie transpile do niczego: typescriptlang.org/play/#code/...
apollo

38

declare w maszynopisie:

declareKluczowe w maszynopisie jest przydatna dla mówienie maszynopis kompilator, że deklaracja jest zdefiniowana gdzieś indziej (gdzieś napisane w zewnętrznym pliku JavaScript lub części środowiska wykonawczego).

Powiedzmy, że mamy zmienną o nazwie foo zadeklarowaną gdzie indziej. Gdy następnie spróbujemy odwołać się do zmiennej, kompilator maszynopisów zgłosi błąd:

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

Możemy rozwiązać ten problem za pomocą declaresłowa kluczowego:

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

Ma to następujące konsekwencje:

  • Gdy foofaktycznie nie jest zadeklarowany nigdzie indziej, i próbujemy użyć zmiennej, może wystąpić błąd czasu wykonywania. Dlatego używaj declaresłowa kluczowego tylko wtedy, gdy wiesz, że zmienna jest dostępna w tym momencie.
  • Ponieważ znamy typy, (potencjalnie) uzyskujemy dostęp do naszej Intellisense IDE .
  • Ponieważ znamy typy, kompilator maszynopisu może sprawdzać typy w czasie kompilacji i może nas ostrzec, jeśli w niektórych scenariuszach używamy niewłaściwych typów.

18

Stwierdzenie kluczowe w tym konkretnym przypadku:

export declare class Actions {
    ...
}

... jest najwyraźniej bezużyteczny i myślę, że TypeScript powinien rozważyć zrobienie z tego błędu (nie wiem, czy jest jakiś ukryty powód). Jeśli zadeklarujesz klasę, nigdy nie będziesz musiał jej importować. Jeśli eksportujesz klasę oczekującą, że ktoś ją zaimportuje, nie musisz jej deklarować. A ponieważ deklarujesz tę klasę, z definicji ta klasa powinna być użyteczna bez konieczności jej importowania. Ale nie jest to prawdą, gdy eksportujesz deklarujesz klasę. Ci muszą importować go używać.

TL; DR

export declare class Actions {
    ...
}

jest taki sam jak

declare class Actions {
    ...
}

Nie sądzę, że są takie same, z pierwszą potrzebą import, z drugą nie
Ian Zhong

10

declare - bez żadnych słów kluczowych importu lub eksportu - definiuje pliki deklaracji automatycznie wybierane przez TypeScript, co jest przydatną funkcją dodawania pisania do starszych modułów (npm zainstalowane pakiety bez definicji TypeScript).

import/ exportjest właściwym sposobem korzystania z modułów i wszystko musi być ręcznie (i uważam to za nieco żmudne) zaimportowane, albo to logika, albo definicje.

Jako praktyczny przypadek użycia export declarepozwala uniknąć eksportu wszystkich podelementów, np .:

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

Które może być łatwiejsze do odczytania niż:

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

Zewnętrzny import jest taki sam w obu przypadkach (np. import { Redux } from 'definitions/redux';), Co nie wiem, czy to dobra praktyka, czy nie, ale uważam, że jest uporządkowane! ^^

Należy pamiętać, że dodanie pliku importlub exportdo pliku spowoduje, że będzie on modułem, dlatego declarezakres nie będzie już na poziomie globalnym.

PS, jest błąd ( problem 16671 ): jeśli użyjesz const enumw swojej deklaracji (robię to dla działań typu redux) i podasz transpileOnlyflagę ( robi to pakiet create- reaguj -aplikacja-maszynopis , dlatego wiem), wyliczenie nie będzie wstawiane! Możesz w nim biegać, możesz nie, ale warto wiedzieć wcześniej!


Przestrzenie nazw wewnątrz modułów nieexport namespacedobrym pomysłem i dodają niepotrzebne przestrzenie nazw . Jeśli chodzi o export declare, spójrz na odpowiedź André Peny.
for0404
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.