使用多个管道时 RXJS 类型推断如何工作打字稿

How RXJS type inference work when multiple pipe is used typescript

const of = require('rxjs').of;
const map = require('rxjs/operators').map

of(123).pipe(
  map(num => num.toString()),
  map(str => str.substring(0,1)),
).subscribe(console.log);

在上面的第二个map中,str参数的类型由前面的map正确推断为returns一个string。我很好奇打字稿是如何推断第二个地图运算符中的类型的。

难道是这个RxJS 把代码设计得很好才可以实现的吗?
还是只是 VS 代码对 RxJS 有特殊的 IntelliSense?

我会说这都是由 RxJS 处理的。

正在查看 pipe overloads

pipe(): Observable<T>;
  pipe<A>(op1: OperatorFunction<T, A>): Observable<A>;
  pipe<A, B>(op1: OperatorFunction<T, A>, op2: OperatorFunction<A, B>): Observable<B>;
  pipe<A, B, C>(op1: OperatorFunction<T, A>, op2: OperatorFunction<A, B>, op3: OperatorFunction<B, C>): Observable<C>;
...

我们可以看到发生了很多事情。

OperatorFunction<T, A> 类型是指一个函数,其单个参数是 T 类型的 Observable 并且其 return type 也是一个类型为 A:

的 Observable
export interface OperatorFunction<T, R> extends UnaryFunction<Observable<T>, Observable<R>> {}

我们也来看看map's signature

export function map<T, R>(project: (value: T, index: number) => R, thisArg?: any): OperatorFunction<T, R> { ... }

如您所见,它的 return 类型将是一个函数,它接收一个 observable 和 returns 另一个 observable。在这种情况下,returned Observable(R) 的 typeinferred 来自提供的投影函数:(value: T, index: number) => R

所以,如果你有

const src$ = of(1).pipe(map(v => '' + v));

src$ 将是一个类型 T 将是 string 的可观察对象。

这就是为什么类型推断也适用于 subscribe:

subscribe(next?: (value: T) => void, error?: (error: any) => void, complete?: () => void): Subscription; // Providing callbacks

subscribe(observer?: PartialObserver<T>): Subscription; // Providing an observer object

其中 T 是 Observable 的推断类型(即在这种情况下来自 map 提供的 fn)。