Преобразование строки в перечисление Typescript в операторе шаблона Angular 6

У меня есть простое приложение Angular 6 с материалом Angular выберите компонент, который мне нужен для двусторонней привязки к переменной перечисления. Для этого мне нужно преобразовать между строковым значением, которое используется для идентификации параметров, и значением перечисления, которое является фактическим типом Typescript. Чтобы преобразовать строку в перечисление, я всегда делал это (при условии, что Value1 является членом MyEnum):

let s: string = "Value1";
let myEnumVariable: MyEnum = MyEnum[s];

но это, похоже, не работает в операторах шаблонов Angular, например. для следующего:

app.component.html:

<mat-form-field>
  <mat-select placeholder="Select a value" [value]="MyEnum[myVariable]" (valueChange)="myVariable = MyEnum[$event]">
    <mat-option value="Value1">Value 1</mat-option>
    <mat-option value="Value2">Value 2</mat-option>
  </mat-select>
</mat-form-field>

app.component.ts:

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'app';
  public myVariable: MyEnum = MyEnum.Value1;
  public MyEnum = MyEnum;
}

enum MyEnum {
  Value1,
  Value2
}

Все в порядке при разработке с сервером разработки Angular. Но как только я запускаю ng build --prod, появляется эта ошибка:

ОШИБКА в src\app\app.component.html(2,73): Тип «строка» не может быть назначен типу «MyEnum».

Почему это должно появиться в строительстве, а не в разработке? Есть идеи, как это исправить, не используя явный вызов метода в операторе шаблона?

Большое спасибо!

P.S. Я использую Typescript 2.7.2.


person scharnyw    schedule 15.11.2018    source источник
comment
@yurzui Это исправляет это! Но Angular в коде VS дает статическую ошибку проверки - [Angular] Неизвестный метод '$ any'. Любой способ удалить это? И если вы хотите, вы можете опубликовать это как ответ, и я могу пометить его как принятый :)   -  person scharnyw    schedule 15.11.2018
comment
Похоже, языковая служба Angular еще не поддерживает $any, но AOT поддерживает angular.io/guide/aot-compiler#disabling-type-checking-using-any   -  person yurzui    schedule 15.11.2018
comment
Вот почему это не работает в aot. stackblitz.com/edit/angular-bpgmal?file= src/app/ AOT обрабатывает $event как any.   -  person yurzui    schedule 15.11.2018
comment
Другой вариант, который вы можете попробовать, это (change)="myVariable = MyEnum['' + $event];"   -  person yurzui    schedule 15.11.2018
comment
Теперь это имеет большой смысл. Большое спасибо!   -  person scharnyw    schedule 15.11.2018


Ответы (2)


Ваш шаблон не распознает его как enum, поэтому вам нужно просто назначить его как строку и прочитать как enum в typescript. Я не уверен, что это правильный способ, но вы можете попробовать

Каждый enum будет сопоставлять значения с ключевыми параметрами и рассмотрит возможность передачи ключа и получения желаемого результата в вашем ключе enum, который кажется number, и вы пытаетесь получить его как string, поэтому измените его следующим образом.

enum MyEnum {
  Value1 = "Value1",
  Value2 = "Value2"
}

Теперь, когда вы прочитаете его как MyEnum.Value1.toString(), он вернет вам конкретное значение как «Value1».

Теперь прочитайте это так: public myVariable: string = MyEnum.Value1.toString() переход к шаблону должен иметь свойство ne string, если вы хотите прочитать его в ts, вы можете передать желаемое string, чтобы получить значение из enum

<mat-form-field>
  <mat-select placeholder="Select a value" [value]="myVariable" (valueChange)="myVariable = $event">
    <mat-option value="Value1">Value 1</mat-option>
    <mat-option value="Value2">Value 2</mat-option>
  </mat-select>
</mat-form-field>

Я надеюсь, что это поможет вам - попробуйте собрать свой проект в ng build --prod и проверьте, работает ли он - Удачного кодирования!!

person Rahul    schedule 15.11.2018
comment
Это наверняка сработает. Но значит ли это, что невозможно связать переменную enum напрямую в Angular? - person scharnyw; 15.11.2018
comment
Нет, это не так, что вы можете связать в template, это будет работать для сборки dev, но у меня была проблема, подобная вашей, в сборке prod, поэтому я нашел способ ее получить :) надеюсь, что это поможет вам - person Rahul; 15.11.2018
comment
Спасибо! yurzui нашел и объяснил решение в комментариях к вопросу. Это связано с тем, как Angular AOT обрабатывает операторы шаблонов. - person scharnyw; 15.11.2018

Попробуй это.

let s = 'Value1' as 'Value1';
let myEnumVariable: MyEnum = MyEnum[s];

У вас была ошибка, потому что Typescript посчитал, что s имеет тип string, а не Value1. Но перечисление имеет определенные ключи Value1 и Value2, а не строку. Отсюда ошибка.

Почему это должно появиться в строительстве, а не в разработке?

Вероятно, во время разработки у вас есть файловый наблюдатель, который компилирует вашу TS в JS, даже если есть какие-то ошибки. У меня есть такой же наблюдатель в моем VSCode. Однако ошибки все еще присутствуют, и поэтому процесс сборки выдает ошибку.

person Nurbol Alpysbayev    schedule 15.11.2018
comment
Извините, но проблема не в этом. Если я не пояснил в вопросе, проблема связана с оператором шаблона в привязке события Angular, где я пытаюсь установить значение переменной перечисления - person scharnyw; 15.11.2018
comment
Привет @scharnyw Помогло? Я обновлял его несколько раз. - person Nurbol Alpysbayev; 15.11.2018
comment
Большое спасибо за ответ! К сожалению, оператор шаблона Angular не принимает Typescript в качестве оператора. Кстати, преобразование из строки в перечисление отлично работает при отладке в ng serve (я проверил, работает ли привязка), оно работает даже с ng build (я разместил сгенерированные и проверенные файлы в браузере), но по какой-то причине это не работает с ng build --prod. Мне кажется, это должны быть какие-то довольно странные функции с производственной сборкой/оптимизацией Angular. - person scharnyw; 15.11.2018
comment
Тот факт, что ng build --prod не работает, это хорошо, потому что он не должен передавать ошибки типа. Что касается приведения типов в шаблонах, возможно, это поможет: stackoverflow.com/questions/45964576/ - person Nurbol Alpysbayev; 15.11.2018
comment
В порядке. Кажется, что нет другого выбора, кроме как иметь метод в TS для этой цели. Большое спасибо! - person scharnyw; 15.11.2018