Angular 具有通用类型的 rxjs 可重用管道逻辑
Angular rxjs reusable pipe logic with generic type
我有一个基本的服务和模型来获取一些看起来像这样的数据:
//api.model.ts
interface ApiErrorResponse {
hasError: boolean;
error?: {
code: number;
errorDomain: string;
description: string;
field: string;
};
}
interface ApiGetResponse<T> extends ApiErrorResponse {
response?: {
items?: T[];
};
}
//some.service.ts
import ...
interface Item {
name: string;
value: number;
}
type ItemApiResponse = ApiGetResponse<Item>;
class SomeUnNamedService {
constructor(private http: HttpClient) {
public getSomeData( userId: number): Observable<ItemApiResponse> {
this._loadingSubject.next(true);
this._errorSubject.next(false);
return this.http.post<ItemApiResponse>(
`${environment._API_}/Some/Api/EndPoint`,
{
userId
}
).pipe(
map( res => {
if(res.response?.items?.length === 0) {
this._emptySubject.next(true);
}
return res;
}),
catchError((err: ApiErrorResponse) => {
this._errorSubject.next(true);
return throwError(err);
}),
finalize(() => this._loadingSubject.next(false))
);
}
以上代码有效,一切正常。但是我的计划是让这个管道(?)运算符(?)可重用,因为我将在多个服务中使用它。所以我在
的帮助下创建了这个
function responseObserver<T>(thisArg) {
return pipe(
map((res: T) => {
// Property 'response' does not exist on type 'T'.
console.log(res?.response);
thisArg._emptySubject.next(true);
return res;
}),
catchError((err: ApiErrorResponse) => {
thisArg._errorSubject.next(true);
return throwError(err);
}),
finalize(() => thisArg._loadingSubject.next(false))
);
}
// I invoke it like this:
public getSomeData(
userId: string,
): Observable<ItemApiResponse> {
.....
return this.http
.post<ItemApiResponse>(
`${environment._API_}/Some/Api/Endpoint`,
{
userId
}
)
.pipe(responseObserver<ItemApiResponse>(this));
}
然而正如您所见,TS 编译器抱怨 'response' 没有退出...
我在这里错过了什么?为什么编译器不能解释泛型?
我正在使用 TypeScript 3.8
您假设泛型类型将包含 response
属性,但您没有定义任何规则让编译器做出该假设。在您的功能上添加这样的规则 -
function responseObserver<T extends ApiGetResponse <T>>(thisArg)
- 应该允许您从泛型类型访问响应 属性 而不会出现编译器错误,因为它让编译器知道您的泛型类型将具有 ApiGetResponse 对象的属性,该对象确实具有响应 属性.
我有一个基本的服务和模型来获取一些看起来像这样的数据:
//api.model.ts
interface ApiErrorResponse {
hasError: boolean;
error?: {
code: number;
errorDomain: string;
description: string;
field: string;
};
}
interface ApiGetResponse<T> extends ApiErrorResponse {
response?: {
items?: T[];
};
}
//some.service.ts
import ...
interface Item {
name: string;
value: number;
}
type ItemApiResponse = ApiGetResponse<Item>;
class SomeUnNamedService {
constructor(private http: HttpClient) {
public getSomeData( userId: number): Observable<ItemApiResponse> {
this._loadingSubject.next(true);
this._errorSubject.next(false);
return this.http.post<ItemApiResponse>(
`${environment._API_}/Some/Api/EndPoint`,
{
userId
}
).pipe(
map( res => {
if(res.response?.items?.length === 0) {
this._emptySubject.next(true);
}
return res;
}),
catchError((err: ApiErrorResponse) => {
this._errorSubject.next(true);
return throwError(err);
}),
finalize(() => this._loadingSubject.next(false))
);
}
以上代码有效,一切正常。但是我的计划是让这个管道(?)运算符(?)可重用,因为我将在多个服务中使用它。所以我在
function responseObserver<T>(thisArg) {
return pipe(
map((res: T) => {
// Property 'response' does not exist on type 'T'.
console.log(res?.response);
thisArg._emptySubject.next(true);
return res;
}),
catchError((err: ApiErrorResponse) => {
thisArg._errorSubject.next(true);
return throwError(err);
}),
finalize(() => thisArg._loadingSubject.next(false))
);
}
// I invoke it like this:
public getSomeData(
userId: string,
): Observable<ItemApiResponse> {
.....
return this.http
.post<ItemApiResponse>(
`${environment._API_}/Some/Api/Endpoint`,
{
userId
}
)
.pipe(responseObserver<ItemApiResponse>(this));
}
然而正如您所见,TS 编译器抱怨 'response' 没有退出... 我在这里错过了什么?为什么编译器不能解释泛型? 我正在使用 TypeScript 3.8
您假设泛型类型将包含 response
属性,但您没有定义任何规则让编译器做出该假设。在您的功能上添加这样的规则 -
function responseObserver<T extends ApiGetResponse <T>>(thisArg)
- 应该允许您从泛型类型访问响应 属性 而不会出现编译器错误,因为它让编译器知道您的泛型类型将具有 ApiGetResponse 对象的属性,该对象确实具有响应 属性.