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 namespace są dobrym 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.