`race`函数引发Typescript异常,即使它工作正常

`race`函数引发Typescript异常,即使它工作正常,typescript,rxjs,Typescript,Rxjs,我有两个观测值。第一个发出数字,第二个发出字符串 当某些触发器发出时,这两个可观察对象开始发出。触发器是主体,两个观察对象中的每一个都有自己的触发器 我想在两个可观测对象之间开始一场竞赛,这样其触发器首先发射的可观测对象获胜并开始发射,而另一个被忽略,即使其触发器随后发射 这是密码 const observableOfNumber = interval(100).pipe(take(10)); const observableOfNumberFunction = () => observa

我有两个观测值。第一个发出
数字
,第二个发出
字符串

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

我想在两个可观测对象之间开始一场
竞赛
,这样其触发器首先发射的可观测对象获胜并开始发射,而另一个被忽略,即使其触发器随后发射

这是密码

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停止抱怨,一切都很完美

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

有人能告诉我这种不同行为的原因吗?

之所以会发生这种情况,是因为返回的类型与首先从其参数发出的类型相同(即,比赛获胜者)可观察的类型

在您的示例中,竞赛获胜者的类型为
number
,因为类型检查器可能(可能)也将第一个参数的类型作为返回类型进行评估,然后期望每个后续发射的类型相同(实际上不是)。如果要切换参数,您会注意到IntelliSense将为您的
emittingNumbers
param提供相同的错误。这就是IDE抱怨但代码仍然运行的原因

下面是一个更明确的例子:

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{
可见的,
间隔
主题,,
比赛
}=rxjs;
常数{
地图,
拿
合并地图,
马普托
}=rxjs.运算符;
常量obs1=间隔(1000)。管道(映射到(“快速一”);
常量obs2=间隔(3000)。管道(映射到(1));//TypeScript将对此进行投诉
常量obs3=间隔(5000)。管道(映射到(“慢一”);
比赛(obs3、obs1、obs2)
.订阅(
winner=>console.log(winner)
);
之所以发生这种情况,是因为返回的类型与首先从其参数发出的类型相同(即,比赛获胜者)
可观察的类型

在您的示例中,竞赛获胜者的类型为
number
,因为类型检查器可能(可能)也将第一个参数的类型作为返回类型进行评估,然后期望每个后续发射的类型相同(实际上不是)。如果要切换参数,您会注意到IntelliSense将为您的
emittingNumbers
param提供相同的错误。这就是IDE抱怨但代码仍然运行的原因

下面是一个更明确的例子:

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{
可见的,
间隔
主题,,
比赛
}=rxjs;
常数{
地图,
拿
合并地图,
马普托
}=rxjs.运算符;
常量obs1=间隔(1000)。管道(映射到(“快速一”);
常量obs2=间隔(3000)。管道(映射到(1));//TypeScript将对此进行投诉
常量obs3=间隔(5000)。管道(映射到(“慢一”);
比赛(obs3、obs1、obs2)
.订阅(
winner=>console.log(winner)
);

您可以像这样显式地为
race
指定联合类型参数:
race Observable>(emittingNumbers,emittingChars)
@cartant@Und3rTow:感谢您的回复-我还有一点想提-为什么
merge
的行为会有所不同?我试图查看代码,但不知何故在各种定义中迷失了方向-但是,从逻辑角度来看,我希望
race
merge
在类型检查时表现相同。您可以像这样显式地为
race
指定联合类型参数:
race Observable>(排放编号、排放字符)
@cartant@Und3rTow:谢谢你的回复-我还有一点想提-为什么
merge
的行为会有所不同?我试图查看代码,但不知何故在不同的定义中迷失了方向-但是,从逻辑的角度来看,我希望
race
merge
在出现问题时表现相同o类型检查。