种族函数引发Typescript异常,即使它工作得很好

时间:2018-06-24 19:18:04

标签: typescript rxjs

我有2个可观察值。第一个发出numbers,第二个发出strings

这两个Observables在某些触发器发出时开始发出。触发是主题,两个可观察对象中的每个都有其自己的触发。

我想在两个Observable之间开始race,以便其触发发出第一个获胜的Observable并开始发出,而另一个触发则随后触发也被忽略。

这是代码

const observableOfNumber = interval(100).pipe(take(10));
const observableOfNumberFunction = () => observableOfNumber;

const observableOfString = interval(100).pipe(map(number => String.fromCharCode(65 + number)), take(10));
const observableOfStringFunction = ()  => observableOfString;

const startEmittingNumbers = new Subject<any>()
const emittingNumbers = startEmittingNumbers
                        .pipe(
                            map(() => observableOfNumberFunction),
                        );

const startEmittingChars = new Subject<any>()
const emittingChars = startEmittingChars
                        .pipe(
                            map(() => observableOfStringFunction),
                        );


race(emittingNumbers, emittingChars)
.pipe(
    mergeMap(handler => handler())
)
.subscribe(console.log);

此代码使Typescript出现以下错误

enter image description here

尽管如此,该代码在本质上似乎运行良好。

如果我只是将observableOfStringFunction的返回类型声明为Observable<any>,即

const observableOfStringFunction = (): Observable<any>  => observableOfString;

Typescript不再抱怨,一切正常。

类似地,如果我不是使用race而是使用merge,即使从类型检查的角度来看,mergerace应该使用Typescript也不会抱怨表现相同。

有人能指出我这种不同行为的原因吗?

1 个答案:

答案 0 :(得分:2)

之所以会发生这种情况,是因为race返回的 type type 相同,后者首先从其参数发出(例如,比赛获胜者)-{ {1}}。

在您的示例中,竞赛获胜者的类型为Observable<T>,因为类型检查器可能(也可能)将第一个参数的类型也作为返回类型进行评估,然后期望随后的每个发射都相同类型(不是)。如果要改变参数,您会注意到IntelliSense将为您的number参数带来相同的错误。这就是为什么IDE抱怨但代码仍然可以运行的原因。

这是一个更明确的示例:

emittingNumbers

const obs1 = interval(1000).pipe(mapTo('fast one')); // Emits first, type string
const obs2 = interval(3000).pipe(mapTo(1)); // Type number, TypeScript will complain
const obs3 = interval(5000).pipe(mapTo('slow one'));

race(obs3, obs1, obs2)
.subscribe(
  winner => console.log(winner)
);
const {
  Observable, 
  interval,
  Subject,
  race
} = rxjs;
const { 
  map, 
  take, 
  mergeMap,
  mapTo 
} = rxjs.operators;

const obs1 = interval(1000).pipe(mapTo('fast one'));
const obs2 = interval(3000).pipe(mapTo(1)); // TypeScript will complain about this
const obs3 = interval(5000).pipe(mapTo('slow one'));

race(obs3, obs1, obs2)
.subscribe(
  winner => console.log(winner)
);