如何为可接收返回字符串/对象数组的函数及Angular指令Input做类型标注
问题原因
你没有给泛型T添加类型约束,TypeScript无法推断T的可能类型,所以访问字符串的toLowerCase()方法、对象的value属性时,都会报类型不存在的错误。同时你原来的运行时类型判断没有和TypeScript的类型收窄逻辑关联,TS无法识别分支内的变量类型。
解决方案
完整修改后的代码如下:
// 定义对象数组的项类型约束 interface FilterOption { value: string; [key: string]: any; // 兼容对象的其他自定义属性 } // 给泛型T添加类型约束,仅允许传入字符串或符合FilterOption结构的对象 export class SelectFilteringDirective<T extends string | FilterOption> { @Input() readonly optionsList: T[] = []; @Output() filteredList = new EventEmitter<T[]>(); constructor() {} @HostListener('keyup', ['$event']) onKeyup(event: Event): void { this.filteredList.emit( this.filterList( this.optionsList, (event.target as HTMLInputElement).value ) ); } private filterList(data: T[], value: string): T[] { // 处理空数组边界情况,避免读取data[0]报错 if (!data.length) return []; const searchKey = value.toLowerCase(); // 类型谓词:告诉TS如果返回true,item就是string类型 const isStringItem = (item: T): item is string => typeof item === 'string'; // 类型谓词:告诉TS如果返回true,item就是FilterOption类型 const isObjectItem = (item: T): item is FilterOption => typeof item === 'object' && 'value' in item; return [...data].filter(item => { if (isStringItem(item)) { return item.toLowerCase().includes(searchKey); } if (isObjectItem(item)) { return item.value.toLowerCase().includes(searchKey); } return false; }) } }
核心修改点
- 给泛型
T添加了extends string | FilterOption约束,限制输入数组的项只能是两种允许的类型 - 新增了带类型谓词的类型判断函数,让TypeScript可以正确收窄每个分支的变量类型,不会再报属性不存在的错误
- 处理了空数组的边界场景,避免空列表时运行时报错
- 把
filterList的返回值从any改为了T[],符合类型安全要求
内容的提问来源于stack exchange,提问作者JanuszFrontEnd'u
相关产品推荐
相关产品推荐

