【问题标题】:RxJS Custom operator with typescript Union type具有打字稿联合类型的 RxJS 自定义运算符
【发布时间】:2021-12-29 18:38:19
【问题描述】:

我有以下型号:

export interface IModel<T> {
 exp: number,
 value: T
}

我想创建一个自定义的 RxJS 运算符,例如:

private customOperator<U extends A | B, T extends IModel<U>>(custom: Observable<T>): Observable<U> {
    return custom.pipe(map((x: T) => x.value ));
  }

但我在使用时遇到类型错误:

  mySub:  = new Subject<IModel<A>>;
  myObs$: Observable<A> = this.mySub.asObservable().pipe(this.customOperator); // <== ERROR

错误:无法分配类型'Observable' 来输入'Observable'。

关于如何更改自定义运算符以避免问题的任何想法?

【问题讨论】:

  • 你能告诉用例吗?据我所知,该问题提供了正确答案。但我也想知道通用运算符函数在哪个用例中对您有用。谢谢。

标签: angular typescript rxjs observable typeerror


【解决方案1】:

将操作符包装在工厂函数中。

private customOperator<T extends IModel<U>, U extends A | B> () {
  return (custom: Observable<T>): Observable<U> =>
   custom.pipe(map((x: T) => x.value ));
}

然后在管道中使用操作符作为函数调用而不是函数引用。

myObs$: Observable<A> = this.mySub.asObservable().pipe(this.customOperator());

干杯

【讨论】:

  • pipe 已经返回一个 observable...asObservable 这里是多余的。 ?
【解决方案2】:

您需要使用 Typescript type assertion 功能。

在您的情况下,编译器会抱怨,因为 myObs$ 必须Observable&lt;A&gt; 类型,而您的自定义运算符可以返回 either Observable&lt;A&gt; orObservable&lt;B&gt;

因此,如果您想避免该错误,您需要向 Typescript 保证您的自定义运算符肯定会返回 Observable&lt;A&gt;。这是避免对 Typescript 编译器进行合法检查的技巧,因此您最好确保自己做的是正确的事情。

所以代码应该是这样的

myObs$: Observable<A> = this.mySub.asObservable().pipe(this.customOperator) as Observable<A>;

或者,更简单的

myObs$ = this.mySub.asObservable().pipe(this.customOperator) as Observable<A>;

如果您将鼠标悬停在 myObs$ 上,例如在 VSCode 中,您将看到为 myObs$ 推断的类型实际上是 Observable&lt;A&gt;,即使您没有指定类型(至少在代码的最后一个版本中) )

更新基于@akotech 的回复

处理这种情况的更好方法是@akotech 提出的方法。

customOperator 如下编码返回Observable&lt;U&gt;

private customOperator<T extends IModel<U>, U extends A | B> () {
  return (custom: Observable<T>): Observable<U> =>
   custom.pipe(map((x: T) => x.value ));
}

有趣的是,至少在我的情况下,如果我没有像这一行那样声明myObs$ 的类型

myObs$ = mySub.pipe(customOperator_())

myObs$ 推断的类型是Observable&lt;A | B&gt;,但同时,如果我尝试这样的事情

myObs$: : Observable<B> = mySub.pipe(customOperator_())

我从编译器得到一个错误Type 'Observable' is notassignable to type 'Observable',这是正确的,因为mySub 通知了IModel&lt;A&gt; 类型的对象.

同时,如果我尝试这样的事情

myObs$: : Observable<A> = mySub_A.pipe(customOperator_())

编译器没有引发错误,这又是正确的。

所以@akotech 提出的解决方案比我提出的解决方案更安全。

【讨论】:

  • 这个答案工作正常,但@akotech 建议的答案似乎不太危险,因为我不必指定我自己的类型。非常感谢您的帮助!
猜你喜欢
  • 2021-08-22
  • 2016-07-07
  • 2021-08-01
  • 1970-01-01
  • 2022-01-05
  • 2018-04-28
  • 2021-08-20
  • 2018-07-04
  • 2019-02-22
相关资源
最近更新 更多