如何在TypeScript中编写带类型的map函数以解决类型不兼容错误?
解决TypeScript中map函数的类型不兼容错误
定义的TypeScript类型
type MapProps = { cb_message_id: string, date: string, name: string, phone: string, email: string, message: string }
原map函数实现
{messageData.map((e: MapProps) => { return ( <Container key={e.cb_message_id} className="flex-col mb-5 px-6 py-4"> <p>{new Date(e.date).toLocaleDateString()}</p> <p className="mt-1">{e.name}</p> <p className="mt-1">{e.phone}</p> <p className="mt-1">{e.email}</p> <p className="mt-1">{e.message}</p> </Container> ) })}
出现的TypeScript错误
Argument of type '(e: MapProps) => JSX.Element' is not assignable to parameter of type '(value: {}, index: number, array: {}[]) => Element'. Types of parameters 'e' and 'value' are incompatible. Type '{}' is missing the following properties from type 'MapProps': cb_message_id, date, name, phone, and 2 more.
错误原因
TypeScript自动推断messageData的类型为{}[](空对象数组),但你在map回调里给参数e指定了MapProps类型,两者类型不匹配,因此抛出错误。本质是要让TypeScript明确messageData的元素类型是MapProps。
解决方案
1. 直接为messageData指定类型
在声明messageData时,明确标注其类型为MapProps[],TypeScript会自动推断map回调的参数类型:
// 声明时指定类型 const messageData: MapProps[] = // 你的数据来源(比如接口返回、本地数据等)
之后map函数可以简化,无需再给e指定类型:
{messageData.map((e) => { return ( <Container key={e.cb_message_id} className="flex-col mb-5 px-6 py-4"> <p>{new Date(e.date).toLocaleDateString()}</p> <p className="mt-1">{e.name}</p> <p className="mt-1">{e.phone}</p> <p className="mt-1">{e.email}</p> <p className="mt-1">{e.message}</p> </Container> ) })}
2. 在map时进行类型断言
如果无法直接给messageData声明类型(比如数据来自第三方库、动态获取),可以在map前对数组进行类型断言:
{(messageData as MapProps[]).map((e) => { return ( <Container key={e.cb_message_id} className="flex-col mb-5 px-6 py-4"> <p>{new Date(e.date).toLocaleDateString()}</p> <p className="mt-1">{e.name}</p> <p className="mt-1">{e.phone}</p> <p className="mt-1">{e.email}</p> <p className="mt-1">{e.message}</p> </Container> ) })}
或者对单个元素断言:
{messageData.map((e) => { const item = e as MapProps; return ( <Container key={item.cb_message_id} className="flex-col mb-5 px-6 py-4"> <p>{new Date(item.date).toLocaleDateString()}</p> <p className="mt-1">{item.name}</p> <p className="mt-1">{item.phone}</p> <p className="mt-1">{item.email}</p> <p className="mt-1">{item.message}</p> </Container> ) })}
3. 使用类型守卫(更严谨)
如果不确定messageData的元素是否完全符合MapProps类型(比如接口返回可能缺失字段),可以编写类型守卫函数做校验,避免运行时错误:
function isMapProps(item: unknown): item is MapProps { if (typeof item !== 'object' || item === null) { return false; } const candidate = item as MapProps; return ( typeof candidate.cb_message_id === 'string' && typeof candidate.date === 'string' && typeof candidate.name === 'string' && typeof candidate.phone === 'string' && typeof candidate.email === 'string' && typeof candidate.message === 'string' ); }
然后在map前过滤符合类型的元素:
{messageData.filter(isMapProps).map((e) => { return ( <Container key={e.cb_message_id} className="flex-col mb-5 px-6 py-4"> <p>{new Date(e.date).toLocaleDateString()}</p> <p className="mt-1">{e.name}</p> <p className="mt-1">{e.phone}</p> <p className="mt-1">{e.email}</p> <p className="mt-1">{e.message}</p> </Container> ) })}
内容的提问来源于stack exchange,提问作者Page COW
相关产品推荐
相关产品推荐

