#angular #typescript #ngrx
#angular #typescript #ngrx
Вопрос:
Недавно я потратил много времени из-за определенного поведения чего-либо (и я не мог определить возможную первопричину) в экосистеме angular / ngrx / typescript.
Сценарий: я создал некоторые эффекты и экспортировал их в файл barrel ( index.ts
):
import {MyEffects} from './my.effects';
export const effects: any[] = [
MyEffects,
];
Затем, в другом файле barrel, на один уровень выше в моей структуре каталогов, у меня есть:
import * as EFFECTS from './effects'
export {EFFECTS};
-store
|-index.ts <= export {EFFECTS}
|-effects
|-index.ts
|-my.effects.ts
И, наконец, в NgModule
массиве imports:
[
...
EffectsModule.forFeature(EFFECTS.effects),
...
]
Когда я попытался скомпилировать это, я получил слишком короткое сообщение об ошибке:
ERROR in params.map is not a function
И ничего больше. И это помешало компиляции моего проекта. И многое другое … при запуске ng serve
также возникала ошибка, но если я что-либо изменил во время ng serve
просмотра изменений файлов, проект просто успешно перекомпилировался.
После целого дня поиска того, что могло быть причиной этого, я выяснил, что часть псевдонима не выполняла то, что, по моему мнению, она должна была делать. Затем я немного изменил структуру, и теперь она работает так, как ожидалось
РЕШЕНИЕ:
В первом файле barrel:
import {MyEffects} from './my.effects';
export const EFFECTS: any[] = [
MyEffects,
];
В файле barrel верхнего уровня:
export * from './effects'
// instead of:
// import * as SOMETHING from './effects'
// export {SOMETHING};
И в NgModel
:
[
...
EffectsModule.forFeature(EFFECTS),
...
]
Но … почему???
Я неправильно понимаю какую-либо часть этого процесса?
Я не уверен, важно ли это, но функция, которая регистрирует эффекты, загружается с задержкой.
Ответ №1:
Вы создаете странную иерархию. export *
и import/export
не ведут себя одинаково.
При использовании export *
TypeScript ведет себя так, как будто все экспортированные символы в этом файле на самом деле находятся внутри файла, даже если они были импортированы из другого места. Другими словами, этот модуль является просто прозрачным уровнем в иерархии, и он полезен только для сокращения путей (вы сможете писать import {foo} from './module'
вместо import {foo} from './module/src/foo
).
Вместо этого, когда вы используете что-то вроде:
import * as smth from './path';
export {smth}
Вы вводите дополнительный уровень, которого раньше не было. И это smth
ключевое слово. Вы не избавитесь от smth
ключа, он есть, и теперь он обертывает весь ваш модуль.
Возвращаясь к вашему примеру, вам следует отредактировать свой вопрос, показывающий, как вы импортируете Effects
в свой NgModule
. Если вы импортировали его как:
import * as effects from './effects.ts';
Затем вы снова вводите новый символ, который переносит все переменные, поэтому правильный путь будет effects.effects.effects.etc
.
Использование деструктурирования и export *
вместо этого позволит вам импортировать и экспортировать переменные без создания оболочек.
Теперь вопрос в том, почему компилятор не предупредил вас? Потому что компилятор typescript обычно хорошо справляется с проблемами такого типа. Решение, скорее всего, здесь:
export const effects: any[] = [
Удалите определение типа ( any[]
) и позвольте TypeScript вмешиваться в тип, я почти уверен, что он покажет вам ошибку, которую вы пропустили.
Комментарии:
1. Когда я сначала загружаю проект сразу после
ng serve
, он выдает мне предупреждение (не ошибку) и не работает. Если я обновляю страницу (без остановки сервера разработки), я не получаю никаких предупреждений, и все работает нормально. Похоже, что компилятор заблудился с двойным косвенным обращением. И я не могу скомпилировать для производства.