如何解决TypeScript对React渲染Date对象的类型报错问题?
问题:解决TypeScript渲染贷款日期字段的类型报错
我正在开发基于Next.js、TypeScript、Prisma和Radix-UI的项目,现有如下贷款对象:
{ "id": 25, "borrowerName": "Test Borrower 1", "pipelineStage": "PROSPECT", "loanAmount": 500000, "transactionType": "PURCHASE", "referralSource": "Realtor Lenny", "borrowerEmail": "test1@gmail.com", "propertyAddress": "1234 Test Way", "borrowerPhone": "789-546-3142", "purchasePrice": 700000, "creditScore": 700, "createdAt": "2024-03-15T21:46:18.347Z", "updatedAt": "2024-03-15T21:46:18.347Z" }
我要构建「查看单个贷款」页面,因使用Prisma,createdAt和updatedAt默认是字符串类型。我编写了遍历对象键值对的代码:
{Object.keys(loan || {}).map((loanKey) => { if (loanKey === "id") return null; if (loan && loanKey in loan) { let value: string | number | Date | null = loan[loanKey as keyof typeof loan]; if (loanKey === "createdAt" || loanKey === "updatedAt") { value = new Date(value!).toLocaleString(undefined, { year: "numeric", month: "long", day: "numeric", hour: "numeric", minute: "numeric", }); } return ( <Card className="text-black"> <Flex direction={"column"} align={"center"}> <Text>{formatKeyDisplay(loanKey)}: </Text> <Card>{value}</Card> </Flex> </Card> ); } return null; })}
我想将createdAt和updatedAt的ISO格式字符串转为友好格式,先转Date对象再用toLocaleString()转回字符串,但渲染value时出现TypeScript报错:
Type 'string | Date | null' is not assignable to type 'ReactNode'. Type 'Date' is not assignable to type 'ReactNode'.ts(2322)
若将value类型定义为string | number | null,则出现另一个报错:
Type 'string | number | Date | null' is not assignable to type 'string | number | null'. Type 'Date' is not assignable to type 'string | number | null'.ts(2322)
解决方案
核心原因
- React无法直接渲染
Date对象,初始类型定义包含Date,导致不满足ReactNode要求 - TypeScript无法自动推断
createdAt/updatedAt分支处理后,value已经转为字符串,仍认为存在Date类型冲突
具体修复方法
方法1:重构逻辑,明确类型推断
调整代码,让TypeScript清晰识别处理后value的类型,同时避免中间Date类型的残留:
{Object.keys(loan || {}).map((loanKey) => { if (loanKey === "id") return null; if (!loan || !(loanKey in loan)) return null; const rawValue = loan[loanKey as keyof typeof loan]; let value: string | number | null; if (loanKey === "createdAt" || loanKey === "updatedAt") { // 直接将ISO字符串转为格式化后的字符串,跳过Date变量的类型歧义 value = rawValue ? new Date(rawValue).toLocaleString(undefined, { year: "numeric", month: "long", day: "numeric", hour: "numeric", minute: "numeric", }) : null; } else { value = rawValue; } return ( <Card className="text-black" key={loanKey}> <Flex direction={"column"} align={"center"}> <Text>{formatKeyDisplay(loanKey)}: </Text> <Card>{value}</Card> </Flex> </Card> ); })}
方法2:类型断言快速修复
如果不想重构逻辑,可在渲染时通过类型断言告诉TypeScript当前value是合法的渲染类型:
// 修改渲染行 <Card>{value as string | number | null}</Card>
额外优化
- 添加
key={loanKey}属性,避免React列表渲染警告 - 对
rawValue为null的情况做兜底,防止new Date(null)生成无效日期
内容的提问来源于stack exchange,提问作者Anthony Garcia
相关产品推荐
相关产品推荐

