Ошибки метаданных AOT¶
28.02.2022
Ниже перечислены ошибки метаданных, с которыми вы можете столкнуться, с пояснениями и предлагаемыми исправлениями.
Форма выражения не поддерживается¶
Компилятор столкнулся с непонятным выражением при оценке метаданных Angular.
Особенности языка, выходящие за рамки ограниченного синтаксиса выражения компилятора, могут вызвать эту ошибку, как показано в следующем примере:
1 2 3 4 5 6 7 8 |
|
Вы можете использовать typeof
и скобочную нотацию в обычном коде приложения. Вы просто не можете использовать эти функции в выражениях, определяющих метаданные Angular.
Избежать этой ошибки можно, придерживаясь ограниченного синтаксиса выражений компилятора при написании метаданных Angular
и остерегайтесь новых или необычных функций TypeScript.
Ссылка на локальный (неэкспортированный) символ¶
Ссылка на локальный (неэкспортируемый) символ 'имя символа'. Рассмотрите возможность экспорта символа.
Компилятор столкнулся со ссылкой на локально определенный символ, который либо не экспортирован, либо не инициализирован.
Вот пример проблемы в provider
.
1 2 3 4 5 6 7 8 9 10 11 |
|
Компилятор генерирует фабрику компонентов, которая включает код поставщика useValue
, в отдельном модуле. Этот модуль фабрики не может вернуться в исходный модуль, чтобы получить доступ к локальной (неэкспортируемой) переменной foo
.
Вы можете решить проблему, инициализировав foo
.
1 |
|
Компилятор свернет выражение в провайдер, как если бы вы написали это.
1 |
|
Альтернативно, вы можете исправить это, экспортируя foo
с расчетом на то, что foo
будет присвоено во время выполнения, когда вы действительно будете знать его значение.
1 2 3 4 5 6 7 8 9 10 11 |
|
Добавление export
часто работает для переменных, на которые ссылаются в метаданных, таких как providers
и animations
, потому что компилятор может генерировать ссылки на экспортируемые переменные в этих выражениях. Ему не нужны значения этих переменных.
Добавление export
не работает, когда компилятору нужно фактическое значение для генерации кода.
Например, это не работает для свойства template
.
1 2 3 4 5 6 7 8 |
|
Компилятору необходимо значение свойства template
прямо сейчас для создания фабрики компонентов. Одной ссылки на переменную недостаточно. Префикс объявления с export
просто выдает новую ошибку, "Only initialized variables and constants can be referenced
".
Только инициализированные переменные и константы¶
На только инициализированные переменные и константы можно ссылаться, потому что значение этой переменной необходимо компилятору шаблона.
Компилятор обнаружил ссылку на экспортируемую переменную или статическое поле, которое не было инициализировано. Для генерации кода ему необходимо значение этой переменной.
Следующий пример пытается установить свойство компонента template
в значение экспортированной переменной someTemplate
, которая объявлена, но не назначена.
1 2 3 4 5 6 7 8 |
|
Вы также получите эту ошибку, если импортируете someTemplate
из другого модуля и не инициализируете его там.
1 2 3 4 5 6 7 8 |
|
Компилятор не может дожидаться времени выполнения, чтобы получить информацию о шаблоне. Он должен статически получить значение переменной someTemplate
из исходного кода, чтобы сгенерировать фабрику компонентов, которая включает инструкции по созданию элемента на основе шаблона.
Чтобы исправить эту ошибку, укажите начальное значение переменной в предложении инициализатора в той же строке.
1 2 3 4 5 6 7 8 |
|
Ссылка на неэкспортированный класс¶
Ссылка на неэкспортированный класс <имя класса>
. Рассмотрите возможность экспорта класса.
Метаданные ссылаются на класс, который не был экспортирован.
Например, вы могли определить класс и использовать его в качестве маркера инъекции в массиве провайдеров, но не экспортировать этот класс.
1 2 3 4 5 6 7 8 |
|
Angular создает фабрику классов в отдельном модуле, и эта фабрика может получить доступ только к экспортированным классам. Чтобы исправить эту ошибку, экспортируйте ссылающийся класс.
1 2 3 4 5 6 7 8 |
|
Ссылка на неэкспортированную функцию¶
Метаданные ссылались на функцию, которая не была экспортирована.
Например, вы могли установить свойство провайдера useFactory
на локально определенную функцию, которую вы забыли экспортировать.
1 2 3 4 5 6 7 8 |
|
Angular создает фабрику классов в отдельном модуле, и эта фабрика может получить доступ только к экспортированным функциям. Чтобы исправить эту ошибку, экспортируйте функцию.
1 2 3 4 5 6 7 8 |
|
Вызовы функций не поддерживаются¶
Вызовы функций не поддерживаются. Подумайте о замене функции или лямбды ссылкой на экспортируемую функцию.
В настоящее время компилятор не поддерживает функциональные выражения или лямбда-функции. Например, вы не можете установить useFactory
провайдера на анонимную функцию или стрелочную функцию, как это сделано здесь.
1 2 3 4 5 6 7 |
|
Вы также получите эту ошибку, если вызовете функцию или метод в useValue
провайдера.
1 2 3 4 5 6 7 8 |
|
Чтобы исправить эту ошибку, экспортируйте функцию из модуля и обратитесь к ней в провайдере useFactory
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Деструктурированная переменная или константа не поддерживается¶
Ссылка на экспортируемую деструктурированную переменную или константу не поддерживается компилятором шаблонов. Рассмотрите возможность упрощения, чтобы избежать деструктуризации.
Компилятор не поддерживает ссылки на переменные, назначенные деструктуризацией.
Например, вы не можете написать что-то вроде этого:
1 2 3 4 5 6 7 8 9 10 11 |
|
Чтобы исправить эту ошибку, обратитесь к неструктурированным значениям.
1 2 3 4 5 6 7 8 |
|
Не удалось определить тип¶
Компилятор встретил тип и не может определить, какой модуль экспортирует этот тип.
Это может произойти, если вы ссылаетесь на окружающий тип. Например, тип Window
является окружающим типом, объявленным в глобальном файле .d.ts
.
Вы получите ошибку, если обратитесь к нему в конструкторе компонента, который компилятор должен статически анализировать.
1 2 3 4 5 |
|
TypeScript понимает окружающие типы, поэтому вы не импортируете их. Компилятор Angular не понимает тип, который вы пренебрегаете экспортом или импортом.
В данном случае компилятор не понимает, как внедрить что-то с помощью маркера Window
.
Не ссылайтесь на окружающие типы в выражениях метаданных.
Если вам необходимо ввести экземпляр окружающего типа, вы можете решить эту проблему в четыре шага:
-
Создайте инъекционный маркер для экземпляра окружающего типа.
-
Создайте фабричную функцию, которая возвращает этот экземпляр.
-
Добавьте провайдер
useFactory
к этой заводской функции. -
Используйте
@Inject
для инъекции экземпляра.
Вот наглядный пример.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Тип Window
в конструкторе больше не является проблемой для компилятора, потому что он использует @Inject(WINDOW)
для генерации кода инъекции.
Angular делает нечто подобное с маркером DOCUMENT
, чтобы вы могли внедрить объект document
браузера (или его абстракцию, в зависимости от платформы, на которой работает приложение).
1 2 3 4 5 6 7 |
|
Имя ожидается¶
Компилятор ожидал увидеть имя в выражении, которое он оценивал.
Это может произойти, если вы используете число в качестве имени свойства, как в следующем примере.
1 2 |
|
Измените имя свойства на нечисловое.
1 2 |
|
Неподдерживаемое имя члена перечисления¶
Angular не смог определить значение enum member, на которое вы ссылались в метаданных.
Компилятор может понимать простые значения перечислений, но не сложные значения, например, полученные из вычисляемых свойств.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Избегайте ссылок на перечисления со сложными инициализаторами или вычисляемыми свойствами.
Выражения шаблонов с метками не поддерживаются¶
Тегированные шаблонные выражения не поддерживаются в метаданных.
Компилятор встретил JavaScript ES2015 tagged template expression, такой как следующий.
1 2 3 4 5 6 |
|
String.raw()
— это теговая функция, встроенная в JavaScript ES2015.
Компилятор AOT не поддерживает выражения шаблонов с метками; избегайте их в выражениях метаданных.
Ожидается ссылка на символ¶
Компилятор ожидал получить ссылку на символ в месте, указанном в сообщении об ошибке.
Эта ошибка может возникнуть, если вы используете выражение в предложении extends
класса.