使用推断来获取装箱的 Observable 值
Using infer to grab the boxed Observable value
我创建了一个 pipe
来将任何源转换为 Observable
,如下所示:
// If T is like an Observable it infers the inner value, otherwise it returns T
type Unobservable<T> = T extends Observable<infer R> ? R : T;
@Pipe({
name: 'toObservable'
})
export class ToObservablePipe implements PipeTransform {
transform<T>(value: T): Observable<Unobservable<T>> {
return isObservable(value) ? value : just(value);
}
}
功能本身有效,但我遇到了 return 类型的问题。目前它显示以下错误:
Type '(T & Observable) | Observable' is not assignable to type 'Observable>'.
Type 'T & Observable' is not assignable to type 'Observable>'.
Type 'unknown' is not assignable to type 'Unobservable'.
只是为了给你介绍一下,管道的使用可以是这样的:
<h4>Array source</h4>
<pre>{{ array | toObservable | async | json }}</pre>
如何制作编译器"happy"? :)
通过这种方式,您可以在不使用推断的情况下获得相同的结果。
import { Pipe, PipeTransform } from "@angular/core";
import { isObservable, Observable, of as just } from "rxjs";
@Pipe({
name: "toObservable"
})
export class ToObservablePipe implements PipeTransform {
transform<T>(value: T): T | Observable<T> {
return isObservable(value) ? value : just(value);
}
}
但如果你想使用推断,我可以建议你这个解决方案
import { Pipe, PipeTransform } from "@angular/core";
import { isObservable, Observable, of as just } from "rxjs";
type Unobservable<T> = T extends Observable<infer R> ? R : T;
type ObservableOrAny<T> = Observable<T> | T;
@Pipe({
name: "toObservable"
})
export class ToObservablePipe implements PipeTransform {
transform<T>(value: ObservableOrAny<T>): Observable<Unobservable<ObservableOrAny<T>>> {
return isObservable(value) ? value : just(value);
}
}
type Unobservable<T> = T extends Observable<infer R> ? R : T;
意味着 Unobservable
可以传递 <T>
的类型,或者 any
因为 R
可以是某种未知类型。
这里 transform<T>(value: T): Observable<Unobservable<T>>
您希望 return 与转换类型相同,但情况并非总是如此,因为我们声明它可以是 any
类型并询问推断它。
要让您的工作发挥作用,请输入 transform response to any。
Observable<Unobservable<any>>
Unobservable到底是什么类型,我不明白它的用途
import { Pipe, PipeTransform } from "@angular/core";
import { isObservable, Observable, of as just } from "rxjs";
type Unobservable<T> = T extends Observable<infer R> ? R : T;
@Pipe({
name: "toObservable"
})
export class ToObservablePipe implements PipeTransform {
transform<T>(value: T): Observable<Unobservable<T>> {
return isObservable(value) ? value as Observable<Unobservable<T>> :
just(value) as Observable<Unobservable<T>>;
}
}
只要你想要,转换都会满足编译器的要求。
您可以改用重载,因为 @angular/AsyncPipe:
import { Pipe, PipeTransform } from '@angular/core';
import { isObservable, Observable, of as just } from 'rxjs';
@Pipe({
name: 'toObservable'
})
export class ToObservablePipe implements PipeTransform {
transform<T>(value: null): null;
transform<T>(value: undefined): undefined;
transform<T>(value: Observable<T> | null | undefined): Observable<T> | null | undefined;
transform<T>(value: T): Observable<T> | null | undefined;
transform(value: Observable<any> | null | undefined): any {
// can be also if (value === null || value === undefined) ...
if (value == null) return value;
return isObservable(value) ? value : just(value);
}
}
部分测试用例:
const obj = { label: 1 };
// Error!
new ToObservablePipe().transform(null).subscribe(response => console.log(response));
// Error!
new ToObservablePipe().transform(undefined).subscribe(response => console.log(response));
// Inferred as string
new ToObservablePipe().transform('').subscribe(response => console.log(response));
// Inferred as number
new ToObservablePipe().transform(0).subscribe(response => console.log(response));
// Inferred as { label: number }
new ToObservablePipe().transform(just(obj)).subscribe(response => console.log(response));
// Inferred as { label: number }[]
new ToObservablePipe().transform([obj]).subscribe(response => console.log(response));
// Inferred as { label: number }
new ToObservablePipe().transform(obj).subscribe(response => console.log(response));
我创建了一个 pipe
来将任何源转换为 Observable
,如下所示:
// If T is like an Observable it infers the inner value, otherwise it returns T
type Unobservable<T> = T extends Observable<infer R> ? R : T;
@Pipe({
name: 'toObservable'
})
export class ToObservablePipe implements PipeTransform {
transform<T>(value: T): Observable<Unobservable<T>> {
return isObservable(value) ? value : just(value);
}
}
功能本身有效,但我遇到了 return 类型的问题。目前它显示以下错误:
Type '(T & Observable) | Observable' is not assignable to type 'Observable>'. Type 'T & Observable' is not assignable to type 'Observable>'. Type 'unknown' is not assignable to type 'Unobservable'.
只是为了给你介绍一下,管道的使用可以是这样的:
<h4>Array source</h4>
<pre>{{ array | toObservable | async | json }}</pre>
如何制作编译器"happy"? :)
通过这种方式,您可以在不使用推断的情况下获得相同的结果。
import { Pipe, PipeTransform } from "@angular/core";
import { isObservable, Observable, of as just } from "rxjs";
@Pipe({
name: "toObservable"
})
export class ToObservablePipe implements PipeTransform {
transform<T>(value: T): T | Observable<T> {
return isObservable(value) ? value : just(value);
}
}
但如果你想使用推断,我可以建议你这个解决方案
import { Pipe, PipeTransform } from "@angular/core";
import { isObservable, Observable, of as just } from "rxjs";
type Unobservable<T> = T extends Observable<infer R> ? R : T;
type ObservableOrAny<T> = Observable<T> | T;
@Pipe({
name: "toObservable"
})
export class ToObservablePipe implements PipeTransform {
transform<T>(value: ObservableOrAny<T>): Observable<Unobservable<ObservableOrAny<T>>> {
return isObservable(value) ? value : just(value);
}
}
type Unobservable<T> = T extends Observable<infer R> ? R : T;
意味着 Unobservable
可以传递 <T>
的类型,或者 any
因为 R
可以是某种未知类型。
这里 transform<T>(value: T): Observable<Unobservable<T>>
您希望 return 与转换类型相同,但情况并非总是如此,因为我们声明它可以是 any
类型并询问推断它。
要让您的工作发挥作用,请输入 transform response to any。
Observable<Unobservable<any>>
Unobservable到底是什么类型,我不明白它的用途
import { Pipe, PipeTransform } from "@angular/core";
import { isObservable, Observable, of as just } from "rxjs";
type Unobservable<T> = T extends Observable<infer R> ? R : T;
@Pipe({
name: "toObservable"
})
export class ToObservablePipe implements PipeTransform {
transform<T>(value: T): Observable<Unobservable<T>> {
return isObservable(value) ? value as Observable<Unobservable<T>> :
just(value) as Observable<Unobservable<T>>;
}
}
只要你想要,转换都会满足编译器的要求。
您可以改用重载,因为 @angular/AsyncPipe:
import { Pipe, PipeTransform } from '@angular/core';
import { isObservable, Observable, of as just } from 'rxjs';
@Pipe({
name: 'toObservable'
})
export class ToObservablePipe implements PipeTransform {
transform<T>(value: null): null;
transform<T>(value: undefined): undefined;
transform<T>(value: Observable<T> | null | undefined): Observable<T> | null | undefined;
transform<T>(value: T): Observable<T> | null | undefined;
transform(value: Observable<any> | null | undefined): any {
// can be also if (value === null || value === undefined) ...
if (value == null) return value;
return isObservable(value) ? value : just(value);
}
}
部分测试用例:
const obj = { label: 1 };
// Error!
new ToObservablePipe().transform(null).subscribe(response => console.log(response));
// Error!
new ToObservablePipe().transform(undefined).subscribe(response => console.log(response));
// Inferred as string
new ToObservablePipe().transform('').subscribe(response => console.log(response));
// Inferred as number
new ToObservablePipe().transform(0).subscribe(response => console.log(response));
// Inferred as { label: number }
new ToObservablePipe().transform(just(obj)).subscribe(response => console.log(response));
// Inferred as { label: number }[]
new ToObservablePipe().transform([obj]).subscribe(response => console.log(response));
// Inferred as { label: number }
new ToObservablePipe().transform(obj).subscribe(response => console.log(response));