Odpowiedzi:
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
externalModulemiędzy innymi zmienną . Jaki może być powód, dla którego externalModulew środowisku wykonawczym jest niezdefiniowany, ale niektóre inne zmienne nie?
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.
declare var myLibrarybędzie transpile do niczego: typescriptlang.org/play/#code/...
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:
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.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 {
...
}
import, z drugą nie
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!
export namespace są dobrym pomysłem i dodają niepotrzebne przestrzenie nazw . Jeśli chodzi o export declare, spójrz na odpowiedź André Peny.