【发布时间】:2021-06-22 12:32:30
【问题描述】:
您好,我有一个基本示例,我不断收到此错误,但我不确定到底是什么问题。
基本上我想在运行时将不同的类型传递给class A。在给定的示例中,它是Order,但我将为Product、Customers 等编写其他类,并且对于所有这些类,我想使用A<T> 作为父类。我还在最小示例下方添加了真实代码。
请有人解释一下解决方案和问题。
interface Order{
customer: {
name: string;
};
}
abstract class A<T>{
protected abstract matches<T>(tableData: T, term: string): boolean;
}
class B extends A<Order>{
protected matches<T extends Order>(tableData: T, term: string): boolean {
return tableData.customer.name.toLowerCase().includes(term.toLowerCase());
}
}
目标是在class B 内访问tableData.customer。我想将Order 作为通用类型传递给matches 方法,但我不确定如何以正确的方式实现。
更新
父类:
export abstract class TableFilterService<T> {
private _loading$ = new BehaviorSubject<boolean>(true);
private _search$ = new Subject<void>();
private _total$ = new BehaviorSubject<number>(0);
private _tableData$: BehaviorSubject<T[]> = new BehaviorSubject([]);
private _data$!: T[];
protected _state: State = {
page: 1,
pageSize: 50,
searchTerm: '',
sortColumn: '',
sortDirection: ''
};
private compare = (v1: string | number, v2: string | number) => v1 < v2 ? -1 : v1 > v2 ? 1 : 0;
protected abstract matches<T>(tableData: T, term: string, pipe: PipeTransform): boolean;
get tableData$() { return this._tableData$.asObservable(); }
get search$() { return this._search$.asObservable(); }
get total$() { return this._total$.asObservable(); }
get loading$() { return this._loading$.asObservable(); }
get page() { return this._state.page; }
get pageSize() { return this._state.pageSize; }
get searchTerm() { return this._state.searchTerm; }
get data() { return this._data$; }
set data(data: T[]) { this._data$ = data; }
set page(page: number) { this._set({page}); }
set pageSize(pageSize: number) { this._set({pageSize}); }
set searchTerm(searchTerm: string) { this._set({searchTerm}); }
set sortColumn(sortColumn: SortColumn) { this._set({sortColumn}); }
set sortDirection(sortDirection: SortDirection) { this._set({sortDirection}); }
constructor(protected pipe: DecimalPipe) {
this._search$.pipe(
tap(() => this._loading$.next(true)),
debounceTime(200),
switchMap(() => this._search()),
delay(200),
tap(() => this._loading$.next(false))
).subscribe(result => {
this._tableData$.next(result.tableData);
this._total$.next(result.total);
});
this._search$.next();
}
protected sort<T>(orders: T[], column: SortColumn, direction: string): T[] {
if (direction === '' || column === '') {
return orders;
} else {
return [...orders].sort((a: any, b: any) => {
const res = this.compare(a[column], b[column]);
return direction === 'asc' ? res : -res;
});
}
}
protected _search(): Observable<SearchResult<T>> {
const {sortColumn, sortDirection, pageSize, page, searchTerm} = this._state;
// 1. sort
let tableData = this.sort(this.data, sortColumn, sortDirection);
// 2. filter
tableData = tableData.filter(data => this.matches(data, searchTerm, this.pipe));
const total = tableData.length;
// 3. paginate
tableData = tableData.slice((page - 1) * pageSize, (page - 1) * pageSize + pageSize);
return of({ tableData, total});
}
private _set(patch: Partial<State>) {
Object.assign(this._state, patch);
this._search$.next();
}
}
儿童班:
export class OrderTableService extends TableFilterService<Order>{
protected matches(tableData: Order, term: string, pipe: PipeTransform): boolean {
return tableData.customer.name.toLowerCase().includes(term.toLowerCase());
}
}
错误:
完整的错误:
Property 'matches' in type 'OrderTableService' is not assignable to the same property in base type 'TableFilterService<Order>'. Type '(tableData: Order, term: string, pipe: PipeTransform) => boolean' is not assignable to type '<T>(tableData: T, term: string, pipe: PipeTransform) => boolean'. Types of parameters 'tableData' and 'tableData' are incompatible. Type 'T' is not assignable to type 'Order'.ts
【问题讨论】:
-
为什么您的
matches方法需要一个类型参数T extends Order,而这仅用于参数?如果它的参数类型只是Order,则该方法将在完全相同的情况下可用,因为T类型的任何参数都是Order的子类型,无论如何都可以分配给Order类型的参数。 -
Order只是一种类型,我还必须传递更多类型。我会有更多像ProductTableService这样的类,其中传递给matches的类型是Product -
如果
ProductTableService是Order的子类型,那么您已经可以传递它而无需泛型类型。如果它不是Order的子类型,那么你不能传递它,因为它不满足类型参数的上限。
标签: typescript typescript-generics