为什么打字稿不能在 RxJs 流中推断元组 return 类型?

Why can't typescript infer tuple return type in RxJs stream?

在组成可观察流时,编译器将从 map 函数返回的元组推断为联合而不是元组。

例如:

import { Component } from '@angular/core';
import { from } from 'rxjs';
import { map, tap } from 'rxjs/operators';

export class MyType {
  constructor(private name: string) {}
}

@Component({
  selector: 'my-app',
  template: ''
})
export class AppComponent {
  observable$ = from([new MyType('obj1'), new MyType('obj2')]).pipe(
    map((value, index) => [value, index]),
    tap(([value, index]) => console.log(value, index))
  ).subscribe();
}

stackblitz 上查看,如果您将鼠标悬停在 tap 中函数参数中的 valueindex 上,它们都会被推断为 number | MyType 当它应该理解为 value: MyTypeindex: number.

如果我通过填写泛型来注释地图:map<MyType, [MyType, number]>(... 那么输入是正确的。

这是预期的行为吗?打字稿不应该在不必显式传递类型的情况下理解该元组吗?

我在本地使用 rxjs @ 6.4.0 和 typescript @ 3.8.3,但 stackblitz 有更新的版本并且仍然出现这种行为。

在您的 map 函数中,您返回的是一个数组,而不是元组。

您可以使用as const强制元组类型:

export class AppComponent {
  observable$ = from([new MyType('obj1'), new MyType('obj2')]).pipe(
    map((value, index) => [value, index] as const),
    tap(([value, index]) => console.log(value, index))
  ).subscribe();
}

参见Tuple Types

array literals with const assertions will be inferred with readonly tuple types