Я бы сказал, что все это обрабатывается Rx JS.
Глядя на pipe
перегрузки
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>
тип относится к функции, единственным параметром которой является Observable типа T
и чей тип возврата также является Observable типа A
:
export interface OperatorFunction<T, R> extends UnaryFunction<Observable<T>, Observable<R>> {}
Давайте также посмотрим на подпись map
export function map<T, R>(project: (value: T, index: number) => R, thisArg?: any): OperatorFunction<T, R> { ... }
Как вы можете видеть, ее тип возврата будет функция, которая получает наблюдаемую и возвращает другую наблюдаемую. В этом случае тип из возвращаемых наблюдаемых (R
) равен выведено из предоставленной функции проекции: (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
- предполагаемый тип наблюдаемого (т. Е. От map
) в этом случае).