Что делает «объявлять» в «действиях по объявлению экспорта»?


Ответы:


212

нашел то, что искал:

Объявить против вар

varсоздает новую переменную. declareиспользуется, чтобы сообщить TypeScript, что переменная была создана в другом месте. Если вы используете declare, к генерируемому JavaScript ничего не добавляется - это просто подсказка компилятору.

Например, если вы используете внешний скрипт, который определяет var externalModule, вы бы использовали declare var externalModuleподсказку для компилятора TypeScript, externalModuleкоторый уже был настроен


У меня есть похожий сценарий с внешним JS, определяющим переменную externalModuleсреди других. В чем может быть причина, почему externalModuleво время выполнения не определено, а некоторые другие переменные нет?
Алехандро Гонсалес

94

Чтобы понять это, вы должны сначала понять ключевое слово «объявлять».

Вот хорошее объяснение из блога Гила Финка :

Ключевое слово декларирования TypeScript используется для объявления переменных, которые могут не происходить из файла TypeScript.

Например, давайте представим, что у нас есть библиотека myLibrary, у которой нет файла объявления TypeScript и в глобальном пространстве имен есть пространство имен myLibrary. Если вы хотите использовать эту библиотеку в своем коде TypeScript, вы можете использовать следующий код:

declare var myLibrary;

Тип, который среда выполнения TypeScript придаст переменной myLibrary, - это любой тип. Проблема в том, что у вас не будет Intellisense для этой переменной во время разработки, но вы сможете использовать библиотеку в своем коде. Другой вариант иметь такое же поведение без использования ключевого слова объявления - просто использовать переменную типа any:

var myLibrary: any;

Оба примера кода приведут к одному и тому же выводу JavaScript, но пример объявления более читабелен и выражает окружающее объявление.


Итак, после того, как вы поймете ключевое слово «объявить», вернитесь туда, где вы найдете

export declare class Action{
...
}

Реальная реализация класса, вероятно, находится где-то еще - возможно, в файле .js.


2
«Оба примера кода приведут к одному и тому же выводу JavaScript», что не соответствует действительности: declare var myLibraryничего не изменится: typescriptlang.org/play/#code/…
apollo

38

declare в машинописи:

declareКлючевое слово в машинописи полезно говорить машинопись компилятор о том , что декларация определяется где - то еще (где - то написано в внешнем файле или части среды выполнения).

Допустим, у нас есть переменная с именем foo, объявленная где-то еще. Когда мы попытаемся сослаться на переменную, компилятор машинописного текста выдаст ошибку:

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

Мы можем решить эту проблему, используя declareключевое слово:

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

Это имеет следующие последствия:

  • Когда fooфактически нигде не объявлено, и мы пытаемся использовать переменную, может произойти ошибка во время выполнения. Так что используйте толькоdeclare ключевое слово только тогда, когда вы знаете, что переменная доступна на данный момент.
  • Поскольку мы знаем типы, мы (потенциально) получаем доступ к нашей IDE Intellisense .
  • Поскольку мы знаем типы, компилятор машинописного текста может проверять типы во время компиляции и может предупреждать нас, если мы используем неправильные типы в определенных сценариях.

18

Объявить ключевое слово в данном конкретном случае:

export declare class Actions {
    ...
}

... очевидно бесполезно, и я думаю, что TypeScript должен рассмотреть возможность сделать это ошибкой (я не знаю, есть ли скрытая причина). Если вы объявляете класс, вам никогда не потребуется его импортировать. Если вы экспортируете класс, ожидая, что кто-то его импортирует, вам не нужно объявлять его. И поскольку вы объявляете этот класс по определению, этот класс должен использоваться без необходимости его импорта. Но это не так, когда вы экспортируете объявление класса. Вам нужно импортировать его, чтобы использовать.

TL; DR

export declare class Actions {
    ...
}

такой же как

declare class Actions {
    ...
}

Я не думаю, что они одинаковы, первый нужно использовать import, а второй нет
Ян Чжун

10

declare - без каких-либо ключевых слов импорта или экспорта - определяет файлы объявлений, автоматически выбираемые TypeScript, что является полезной функцией для добавления типизации в устаревшие модули (установленные пакеты npm без определений TypeScript).

import/ export- это правильный способ использования модулей, и все должно быть импортировано вручную (и я нахожу это немного утомительно), либо это логика, либо определения.

В качестве практического варианта использования export declareпозволяет избежать экспорта всех подэлементов, например:

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

Который может быть легче читать, чем:

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

Внешний импорт одинаков в обоих случаях (например, import { Redux } from 'definitions/redux'; ), что я не знаю, хорошая ли это практика или нет, но я считаю это опрятным! ^^

Важно помнить, что добавление файла importили exportк вашему файлу сделает его модулем, поэтому declareобласть больше не будет на глобальном уровне.

PS, есть ошибка ( проблема 16671 ): если вы используете const enumв своем объявлении (я делаю это для типа действий приставки) и вы указали transpileOnlyфлаг ( пакет create-реагировать-app-typecript делает, поэтому я знаю), enum не будет встроен! Вы можете участвовать в этом, вы не можете, но это полезно знать заранее!


Пространства имен внутри модулей ала export namespaceявляются не очень хорошей идеей и добавить ненужные пространства имен . Что касается export declare, посмотрите на ответ Андре Пена.
ford04
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.