多约束下Angular Material复用表格属性处理问题
解决方案:处理可复用Angular Material表格的异构数据总额计算问题
针对你遇到的泛型包含部分无transactionAmount属性的数据结构,导致方法报错的问题,这里提供几个实用解决思路:
方案1:使用类型守卫过滤有效数据
在getTransactionTotal方法中,通过类型守卫筛选出包含transactionAmount的条目后再求和,既保留单一组件复用性,又避免访问不存在的属性:
interface HasTransactionAmount { transactionAmount: number; } // 类型守卫函数,编译时和运行时都能校验属性存在性 function hasTransactionAmount(item: any): item is HasTransactionAmount { return 'transactionAmount' in item && typeof item.transactionAmount === 'number'; } export class ReusableTable<T extends DataA | DataB | DataC> { @Input() public dataArr: T[] = []; public dataSource!: MatTableDataSource<T>; ngOnInit() { this.dataSource = new MatTableDataSource(this.dataArr); } public getTransactionTotal(): number { return this.dataArr .filter(hasTransactionAmount) .map(t => t.transactionAmount) .reduce((acc: number, value: number) => acc + value, 0); } }
如果传入的是DataB数组,该方法会返回0,符合无相关数据的预期。
方案2:定义通用接口梳理数据结构
先定义包含transactionAmount的基础接口,让DataA和DataC继承它,再结合类型断言确保计算逻辑的安全性:
interface TransactionalData { transactionAmount: number; } interface DataA extends TransactionalData { transactionDate: Date; username: string; } interface DataB { payerFirstName: string; payerLastName: string; monthlyTotal: number; } interface DataC extends TransactionalData { organization: string; username: string; } export class ReusableTable<T extends DataA | DataB | DataC> { @Input() public dataArr: T[] = []; public dataSource!: MatTableDataSource<T>; ngOnInit() { this.dataSource = new MatTableDataSource(this.dataArr); } public getTransactionTotal(): number { return (this.dataArr as TransactionalData[]) .filter(item => 'transactionAmount' in item) .reduce((acc, item) => acc + item.transactionAmount, 0); } }
这种方式通过接口继承梳理了数据结构关系,让类型定义更清晰,计算逻辑也更直观。
方案3:通过输入属性传入自定义计算逻辑
如果不同数据类型的总额计算规则差异较大(比如DataB需要计算monthlyTotal总和),可以让父组件传入计算回调函数,让组件完全适配异构数据需求:
export class ReusableTable<T extends DataA | DataB | DataC> { @Input() public dataArr: T[] = []; @Input() public calculateTotal?: (data: T[]) => number; public dataSource!: MatTableDataSource<T>; ngOnInit() { this.dataSource = new MatTableDataSource(this.dataArr); } public getTransactionTotal(): number { // 优先使用父组件传入的自定义逻辑,否则默认计算transactionAmount总和 if (this.calculateTotal) { return this.calculateTotal(this.dataArr); } return this.dataArr .filter(item => 'transactionAmount' in item && typeof item.transactionAmount === 'number') .reduce((acc, item) => acc + (item as any).transactionAmount, 0); } }
父组件使用时可根据数据类型指定计算逻辑:
<!-- 传入DataB数组时 --> <reusable-table [dataArr]="dataBList" [calculateTotal]="(data) => data.reduce((acc, item) => acc + item.monthlyTotal, 0)" ></reusable-table>
该方案灵活性最高,能应对各种复杂异构数据场景,同时保持组件单一性。
内容的提问来源于stack exchange,提问作者ACDev
相关产品推荐
相关产品推荐

