Как различать общие типы Observable в TypeScript?

Я пытаюсь следовать этому примеру при изучении switchMap для rxjs. Рабочий пример находится здесь и написан на TypeScript. Я попытался написать что-то подобное на TypeScript (Angular 2) в VS Code, но получил ошибку компилятора.

Operator '+' cannot be applied to types 
'Observable | Observable' and 
'Observable | Observable'.
(parameter) curr: Observable | Observable 

Мой код выглядит следующим образом.

playSubject = new Subject<boolean>();
pauseSubject = new Subject<boolean>();
interval$  = Observable.interval(1000).mapTo(-1);
pause$ = Observable.from(this.pauseSubject).mapTo(Observable.of(false));
resume$ = Observable.from(this.playSubject).mapTo(this.interval$);
timer$ = Observable
  .merge(this.pause$, this.resume$)
  .startWith(this.interval$)
  .switchMap(v => Observable.of(v))
  .scan((acc, curr) => {
    return curr ? curr + acc : acc; //problem right here
  });
ngAfterViewInit() {
  this.timer$.subscribe(data => {
    console.log(data);
  });
}
play() { //bound to button click event
  this.playSubject.next(true);
}
pause() { //bound to button click event
  this.pauseSubject.next(false);
}

Я могу изменить код в функции scan следующим образом, но тогда мне нужно будет знать, является ли curr Observable<boolean> или Observable<number>.

playSubject = new Subject<boolean>();
pauseSubject = new Subject<boolean>();
interval$  = Observable.interval(1000).mapTo(-1);
pause$ = Observable.from(this.pauseSubject).mapTo(Observable.of(false));
resume$ = Observable.from(this.playSubject).mapTo(this.interval$);
timer$ = Observable
  .merge(this.pause$, this.resume$)
  .startWith(this.interval$)
  .switchMap(v => Observable.of(v))
  .scan((acc, curr) => {
    return curr; //how do i check for Observable<Type>?
  });

Любая идея о том, что я делаю неправильно или как проверить тип Observable внутри scan?


person Jane Wayne    schedule 31.01.2017    source источник
comment
В чем причина закрытия голосов?   -  person Jane Wayne    schedule 31.01.2017
comment
Почему вы используете Observable.of в switchMap? В приведенном вами примере этого нет.   -  person Szabolcs Dézsi    schedule 31.01.2017
comment
Я получаю ошибку компиляции в VS Code, если я этого не сделаю. Обратите внимание, что пример написан на TypeScript, но задание копирования/вставки в VS Code (внутри проекта Angular 2) не работает.   -  person Jane Wayne    schedule 31.01.2017
comment
Разве проблема не в .startWith(this.interval$), когда вы начинаете последовательность с Observable? Оператор startWith просто повторно передает Observable без подписки на него reactivex. io/rxjs/файл/es6/оператор/   -  person martin    schedule 31.01.2017
comment
Как это проблема? Я почти дословно взял этот код с Learnrxjs.io.   -  person Jane Wayne    schedule 31.01.2017


Ответы (1)


Я думаю, чтобы правильно исправить это в VS Code, вам нужно предоставить транспилятору следующую помощь с параметрами универсального типа:

timer$ = Observable
  .merge(this.pause$, this.resume$)
  .startWith(this.interval$)
  .switchMap<Observable<boolean> | Observable<number>, boolean | number>(v => v)
  .scan<boolean | number, number>((acc, curr) => {
    return curr && typeof curr === "number" ? curr + acc : acc;
  }, 60);

Таким образом, это сообщает транспилеру, что входные данные для switchMap — это Observable<boolean> или Observable<number>, а его выходные данные — либо boolean, либо number.

Затем мы сообщаем методу scan, что его ввод — это либо boolean, либо number, а тип его начального значения — number.

Мы не останавливаемся на этом, потому что транспилятор все равно сбивается с толку, когда он сталкивается с выражением curr + acc. Это потому, что тип currboolean | number, а тип accnumber.

Для этого я ввел в тернарный оператор дополнительное условие: typeof curr === "number", которое делает транспилятор счастливым, и код будет транспилироваться. Это работает благодаря функции под названием: защиты типов.

Также обратите внимание, что Observable.of не обязательно в switchMap.

person Szabolcs Dézsi    schedule 31.01.2017