React.js TypeScript泛型报错:类型'T'无法赋值给'ReactNode'
React泛型List组件渲染报错问题分析
问题场景
编写了一个用于展示条目的泛型List组件(List.tsx),在App.tsx中使用时无报错,但组件内部的{item}处出现类型错误。
List.tsx 代码
type PersonInGeneric = { id: number; first: string; last: string; }; type ListProps<T> = { items: T[]; onClick: (value: T) => void }; export const List = <T extends PersonInGeneric>({ items, onClick, }: ListProps<T>) => { return( <> <h2>List of items</h2> {items.map((item, index) => { return( <div key={item.id} onClick={() => onClick(item)}> {item} </div> ); })} </> ); }
App.tsx 使用代码
<List items={[ { id: 1, first: 'Kai', last: 'Doe', } ]} onClick={item => console.log(item)} />
错误提示
"Type 'T' is not assignable to type 'ReactNode'.
Type 'PersonInGeneric' is not assignable to type 'ReactNode'.
Type 'T' is not assignable to type 'ReactPortal'.
Type 'PersonInGeneric' is missing the following properties from type 'ReactPortal': key, children, type, propsts"
问题原因
React无法直接渲染普通对象类型。这里的T继承自PersonInGeneric,本质是一个对象,而React要求渲染的内容必须属于ReactNode类型(比如字符串、数字、React元素、null等),普通对象不在这个范围内,因此触发类型不兼容错误。
解决方案
方案1:直接渲染对象的具体属性
修改List组件中渲染条目的部分,明确展示对象的字段,而不是直接渲染整个对象:
{items.map((item) => { return( <div key={item.id} onClick={() => onClick(item)}> {/* 渲染具体属性 */} {item.first} {item.last} (ID: {item.id}) </div> ); })}
方案2:添加渲染回调提升组件灵活性
如果希望List组件支持任意类型的条目渲染,可以新增一个renderItem属性,让父组件决定每个条目的渲染逻辑:
- 更新组件Props类型:
type ListProps<T> = { items: T[]; onClick: (value: T) => void; renderItem: (item: T) => React.ReactNode; // 新增渲染回调 };
- 修改List组件实现:
export const List = <T extends PersonInGeneric>({ items, onClick, renderItem, }: ListProps<T>) => { return( <> <h2>List of items</h2> {items.map((item) => { return( <div key={item.id} onClick={() => onClick(item)}> {renderItem(item)} {/* 使用父组件传入的渲染逻辑 */} </div> ); })} </> ); }
- 在App.tsx中使用时传入渲染逻辑:
<List items={[ { id: 1, first: 'Kai', last: 'Doe', } ]} onClick={item => console.log(item)} renderItem={(item) => `${item.first} ${item.last}`} />
内容的提问来源于stack exchange,提问作者marc
相关产品推荐
相关产品推荐

