Псевдоним импорта Typescript файл barrel

#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 , он выдает мне предупреждение (не ошибку) и не работает. Если я обновляю страницу (без остановки сервера разработки), я не получаю никаких предупреждений, и все работает нормально. Похоже, что компилятор заблудился с двойным косвенным обращением. И я не могу скомпилировать для производства.