TypeScript中如何实现约束项继承OrderedItem的自定义SortableList类
这个需求完全可以实现,核心是给SortableList添加带继承约束的泛型,保留传入的列表项子类类型,修改方式如下:
第一步:修改SortableList.ts代码
import OrderedItem from './OrderedItem' // 给类添加泛型T,约束T必须继承自OrderedItem class SortableList<T extends OrderedItem> { // list类型改为泛型T的数组 list: T[] // 构造函数参数也对应为T数组 constructor(list: T[]) { this.list = list } sortByOrder = (): void => { // T继承了OrderedItem,必然有order属性,排序逻辑不受影响 this.list = this.list.sort((a, b) => a.order - b.order) } sortByReverseOrder = (): void => { this.list = this.list.sort((a, b) => b.order - a.order) } } export default SortableList
第二步:修改example.tsx调用代码
两种调用方式都可以正常运行:
import CustomListItem from './CustomListItem' import SortableList from './SortableList' export default function Example() { const customList: CustomListItem[] = [ new CustomListItem(3, 'name3', <div></div>), new CustomListItem(1, 'name1', <div></div>), new CustomListItem(2, 'name2', <div></div>), ] // 方式1:显式传入泛型参数,类型更明确 const sortableList = new SortableList<CustomListItem>(customList) // 方式2:TS自动根据传入的customList推断泛型类型,也可以正常工作 // const sortableList = new SortableList(customList) sortableList.sortByOrder() // 此时item类型为CustomListItem,可以正常访问jsx、name属性,不会报错 return sortableList.list.map(item => item.jsx) }
原报错原因说明
之前的写法将SortableList内部的list固定声明为OrderedItem[]类型,TypeScript只会识别OrderedItem上存在的属性,子类CustomListItem扩展的jsx、name属性都会被类型系统丢弃。通过带约束的泛型可以让SortableList适配所有继承自OrderedItem的子类,同时保留完整的子类类型信息,不会丢失扩展属性的类型定义。
内容的提问来源于stack exchange,提问作者eddiespaghetti
相关产品推荐
相关产品推荐

