Почему преобразование Observable в WritableSignal в Angular 16 выдает ошибку отсутствия свойств

У меня есть следующий простой код на моем компоненте:

      import {Component, effect, signal, WritableSignal} from '@angular/core';
import {AppService} from "../app.service";
import {toSignal} from "@angular/core/rxjs-interop";

@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.css']
})
export class ParentComponent {

  translations: WritableSignal<{data: {}}> = signal({data: []});

  constructor( private appService: AppService) {
    this.translations = toSignal(this.appService.getTranslations());
    effect(() => {
      console.log('translation API:', this.translations());
    });
  }

  changeValue(): void {
    this.translations.set({data: {hello: 'hallo'}})

  }
}

К вашему сведению:this.appService.getTranslations()возвращает наблюдаемую

Я пробую новые функции, выпущенные в Angular v16, и то, как конвертировать Observables в сигналы.

Что я хотел сделать в приведенном выше коде, так это изменить значение объекта WritableSignal и зарегистрировать его значение при изменении.

Я получаю следующую ошибку:

      TS2739: Type 'Signal ' is missing the following properties from type 'WritableSignal{ data: {}; }>': set, update, mutate, asReadonly

Помоги пожалуйста.

1 ответ

Observables доступны только для чтения и, следовательно, не подходят для . Вы можете подписаться на них, но не вызывать такой метод, какnextдля передачи новых данных.
Потенциально объекты можно преобразовать в , но, насколько мне известно, служебного метода не существует.

Ошибка, которую вы получаете, означает, что у объекта, который возвращается, отсутствуют свойства/методы из, все «записываемые»; это версия «только для чтения»WritableSignal.

В этом случае вам следует подписаться на свою наблюдаемую и установить сигнал в обратном вызове.
ЕслиAppServiceиспользуется скрытно, нет необходимости отписываться, поскольку это делается автоматически при первом успешном обратном вызове.

      constructor(private appService: AppService) {
  this.appService.getTranslations().subscribe(data => {
    this.translations.set(data)
  });
  effect(() => {
    console.log('translation API:', this.translations());
  });
}

Если он не используется и вы хотите получить данные только один раз при построении, используйтеfirst()Оператор RxJS.

      constructor(private appService: AppService) {
  this.appService.getTranslations().pipe(first()).subscribe(data => {
    this.translations.set(data)
  });
  effect(() => {
    console.log('translation API:', this.translations());
  });
}

Если он не используетHttpClient, и вам нужно регулярно получать обновления, вам придется отказаться от подписки на уничтожение.
Поскольку вы тестируете предварительную версию Angular 16 для разработчиков, вы можете использовать новыйDestroyRefдля этого, а не дляOnDestroy.ngOnDestroyкрюк.

      constructor(
  private appService: AppService,
  destroyRef: DestroyRef
) {
  const sub = this.appService.getTranslations().subscribe(data => {
    this.translations.set(data)
  });
  destroyRef.onDestroy(() => {
    sub.unsubscribe();
  });
  effect(() => {
    console.log('translation API:', this.translations());
  });
}

И, наконец, если вы все еще хотите использоватьtoSignal, твойtranslationsполе должно иметь тип . Но тогда твойchangeValueметод больше не будет работать, так какSignalне имеет методаset.

Другие вопросы по тегам