如何用TypeScript泛型约束React列表组件仅接受ItemOne或ItemTwo类型项
解决方法
1. 定义联合类型
先把ItemOne和ItemTwo合并成一个联合类型,作为泛型约束的基础:
import { ItemOne, ItemTwo } from './your-path'; // 替换成实际导入路径 export type ListItemType = ItemOne | ItemTwo;
2. 约束泛型参数
修改组件的泛型约束,让T只能是ListItemType的子类型(也就是仅接受ItemOne或ItemTwo):
type Props<T extends ListItemType> = { items: T[]; }; const MyList = <T extends ListItemType>({ items }: Props<T>) => { // 后续逻辑 };
3. 添加类型守卫函数
为了让TypeScript正确区分两种类型,需要定义类型守卫函数,明确判断当前item的类型:
// 利用ItemOne独有的id字段判断类型 const isItemOne = (item: ListItemType): item is ItemOne => { return 'id' in item; }; // 若type字段有固定枚举值,也可以用type判断(比如ItemOne的type为'Type One') // const isItemOne = (item: ListItemType): item is ItemOne => { // return item.type === 'Type One'; // };
4. 修正组件渲染逻辑
在遍历列表时,用类型守卫判断item类型,让TypeScript能正确推断id或uuid的存在:
const MyList = <T extends ListItemType>({ items }: Props<T>) => { return ( <ul css={styles.list}> {items.map((item) => ( <MyListItem key={isItemOne(item) ? item.id : item.uuid} title={item.title} /> ))} </ul> ); };
完整代码示例
import { ItemOne, ItemTwo } from './your-path'; import MyListItem from './MyListItem'; import styles from './styles'; export type ListItemType = ItemOne | ItemTwo; type Props<T extends ListItemType> = { items: T[]; }; const isItemOne = (item: ListItemType): item is ItemOne => { return 'id' in item; }; const MyList = <T extends ListItemType>({ items }: Props<T>) => { return ( <ul css={styles.list}> {items.map((item) => ( <MyListItem key={isItemOne(item) ? item.id : item.uuid} title={item.title} /> ))} </ul> ); }; export default MyList;
修改完成后,组件的items属性仅能接受ItemOne[]、ItemTwo[]或两者混合的数组,传入不符合类型的数组时TypeScript会直接抛出错误。
内容的提问来源于stack exchange,提问作者meez
相关产品推荐
相关产品推荐

