简体   繁体   English

RxJS 如何使用带有多个值的 startWith 的 combineLatest?

[英]RxJS how to use combineLatest with startWith with multiple values?

I have a question about using combineLatest with the startWith operator我对将combineLateststartWith运算符一起使用有疑问

The code below works下面的代码有效

const data_1$ = new Subject<string>();
const data_2$ = new Subject<number>();

viewModel$ = combineLatest([data_1$, data_2$])
   .pipe(map([data_1, data_2]) => {
      return { data_1, data_2 };
   })

however now if I want to use startWith operator但是现在如果我想使用startWith运算符

const data_1$ = new Subject<string>();
const data_2$ = new Subject<number>();

viewModel$ = combineLatest([data_1$, data_2$])
   .pipe(
      startWith(["hello", 1]),
      map([data_1, data_2]) => {
         return { data_1, data_2 };
      })

The map part will infer that data_1 and data_2 can be string | number map部分将推断data_1data_2可以是string | number string | number . string | number Can I get it to infer as the first example which doesn't use startWith ?我可以将它推断为第一个不使用startWith的示例吗? I know about BehaviorSubject and it could be used instead of startWith but in my case I need to use startWith.我知道BehaviorSubject ,它可以用来代替startWith ,但在我的例子中,我需要使用 startWith。

Starting from the official documentation , startWith 's typing is given by:官方文档开始, startWith的类型由以下内容给出:

startWith<T, D>(...values: D[]): OperatorFunction<T, T | D>

In your case, you want to ensure that startWith only returns something of the type [string, number] .在您的情况下,您希望确保startWith仅返回[string, number]类型的内容。

The issue occurs because when you provide the array with ['hello',1] it considers the type as (string|number)[] .出现此问题是因为当您为数组提供['hello',1]时,它会将类型视为(string|number)[] This is because in the generic declaration, only one type, D[] is provided.这是因为在泛型声明中,只提供了一种类型D[] Hence why it considers the type of ['hello',1] to be (string|number)[] , which fits D[] .因此,为什么它认为['hello',1]的类型是(string|number)[] ,它适合D[]

To solve this, you can provide the typing explicitly with the use of the generic:要解决这个问题,您可以使用泛型显式提供类型:

startWith<[string, number]>(['hello', 1])

The question then arises, why does map infer the argument type currently?那么问题来了,为什么map目前推断的是参数类型呢? Well the answer to this is also in the official typing of map :那么这个问题的答案也在map 的官方输入中

map<T, R>(project: (value: T, index: number) => R, thisArg?: any): OperatorFunction<T, R>

In map 's case, it infers the type from the the provided value T .map的例子中,它从提供的值T推断出类型。 Since there is no need to match any array casting, the value of [string, number] is used instead.由于不需要匹配任何数组转换,因此使用[string, number]的值。

You just have to declare the argument passed to the startWith operator with as const .您只需使用const声明传递给startWith运算符的参数。

combineLatest([data_1$, data_2$]).pipe(
 startWith(['hello', 1] as const),
 map(([data_1, data_2]) => (return { data_1, data_2 }))
);

The expression as const makes the compiler treat the array as a readonly tuple.表达式as const使编译器将数组视为只读元组。 That's actually too specific for what you want to use in the map operator.对于您想在map运算符中使用的内容,这实际上太具体了。 However, the startWith operator won't return that tuple type, as it returns the union of the type of the argument and the type passed along the stream. That return type ends up being [string, number] - which is what you want.但是, startWith运算符不会返回该元组类型,因为它返回参数类型和沿 stream 传递的类型的联合。返回类型最终为 [string, number] - 这正是您想要的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM