Bonjour j'ai un exemple de base où je continue à obtenir cette erreur et je ne suis pas sûr de ce que c'est exactement le problème.
Fondamentalement, je veux transmettre différents types à class A
Au moment de l'exécution. Dans l'exemple donné, c'est Order
mais je vais écrire d'autres classes pour Product
, Customers
et plus et pour tous, je veux utiliser A<T>
Comme parent . J'ai également ajouté le code réel en dessous de l'exemple minimal.
Peut plaire à quelqu'un d'expliquer la solution et le problème à cela.
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());
}
}
L'objectif est d'accéder à tableData.customer
Dans class B
. Je veux passer Order
à la méthode matches
comme type générique, mais je ne sais pas comment cela peut être mis en œuvre correctement.
Mise à jour
Classe des parents:
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();
}
}
Classe enfant:
export class OrderTableService extends TableFilterService<Order>{
protected matches(tableData: Order, term: string, pipe: PipeTransform): boolean {
return tableData.customer.name.toLowerCase().includes(term.toLowerCase());
}
}
Erreur:
l'erreur complète:
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
Votre fonction abstrait générique matches<T>
remplace générique T
de la classe A<T>
. Ce que vous avez écrit, c'est fondamentalement ceci:
abstract class A<T>{
protected abstract matches<U>(tableData: U, term: string): boolean;
}
Le générique T
au sommet de la classe était fondamentalement inutile. La solution pourrait ressembler Ceci :
interface Order{
customer: {
name: string;
};
}
abstract class A<T>{
// No generic <T> at the function itself anymore. Now tableData: T refers to A<T>
protected abstract matches(tableData: T, term: string): boolean;
}
class B extends A<Order>{
protected matches(tableData: Order, term: string): boolean {
return tableData.customer.name.toLowerCase().includes(term.toLowerCase());
}
}
class C extends A<Order>{
protected matches<T extends Order>(tableData: T, term: string): boolean {
return tableData.customer.name.toLowerCase().includes(term.toLowerCase());
}
}