Угловой, наблюдаемый предел трубы?

#angular #visual-studio-code #rxjs-observables

Вопрос:

Я делаю это в одном из моих охранников маршрута…

 canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
    // go through each check sequentially, stop process if one does throwError
    return of(true).pipe( // Is there a limit to operators in a pipe???
      switchMap(() => of(true)), // simplified for this post...usually call a function that returns
      switchMap(() => of(true)),
      switchMap(() => of(true)),
      switchMap(() => of(true)),
      switchMap(() => of(true)),
      switchMap(() => of(true)),
      switchMap(() => of(true)),
      switchMap(() => of(true)),
      // if any function returns throwError, we skip other checks
      catchError(() => of(false))
    );
  }
 

Я столкнулся с ошибкой. Если в список будет добавлена еще одна карта переключателей, VSCode сообщит мне об этом…
«Тип «Наблюдаемый< {}>» не может быть присвоен типу «Наблюдаемый».
Тип «{}» не может быть присвоен типу «логический». ts(2322)»

Может ли кто-нибудь объяснить мне, почему это так? Я не могу понять это и найти связанные с этим проблемы.

Ответ №1:

Это довольно хорошо объяснено в этом выпуске github.

Суть в том, что поддерживается только 9 операторов — больше, и он вернется к набору Observable<{}> , так как им придется вручную вводить все до 9 операторов.

Используйте несколько каналов (сохраняет безопасность типа после 9-й записи)

Если вы все еще хотите сохранить безопасность типов, но добавить более 9 операторов, просто снова вызовите функцию pipe.

 source$
  .pipe(
    tap(() => {}),
    tap(() => {}),
    tap(() => {}),
    tap(() => {}),
    tap(() => {}),
    tap(() => {}),
    tap(() => {}),
    tap(() => {}),
    tap(() => {})
  )
  .pipe(
    // Add the next operators after the 9nth here
    tap(() => {}) 
  )
 

Вручную подтвердите полученный тип

Кроме того, вы можете добавить утверждение типа вручную в конце. Однако будьте осторожны: после 9-го оператора тип будет выведен как Observable<{}> фактически теряющий безопасность.

 const source$:Observable<boolean> = of(true)
  .pipe(
    tap(() => {}),
    tap(() => {}),
    tap(() => {}),
    tap(() => {}),
    tap(() => {}),
    tap(() => {}),
    tap(() => {}),
    tap(() => {}),
    tap(() => {}),
    // Typesafety is lost here
    tap(() => {}),
    tap(() => {}),

  // Manually assert the type at the end 
  // Beware that the compiler will allow pretty much anything here,
  // so "as Observable<string>" would work, even though it'd be wrong.
  ) as Observable<boolean>;
 

Комментарии:

1. Нет необходимости, это ведет себя точно так же, как если бы у вас было все в одной трубе. Это необходимо только для получения правильного вывода типа.

2. Так что просто поместите ошибку во вторую трубу?

3. Если вы хотите, чтобы ошибка захвата была последним, что делает ваш наблюдаемый (как в вашем примере выше), да.

4. Извините. Я должен был быть более ясным в посте…каждая из этих карт переключения либо вернет значение(true), либо приведет к ошибке();

5. Лично я не являюсь поклонником этого решения, так как оно останавливает цепочку вывода типов в вашей трубе — в основном теряя всю безопасность типов после 9-й записи. Однако я могу включить это предложение в ссылку 🙂