TypeScript动态表单对象数组类型赋值错误求助(React Hook Form+Zod+Shadcn UI)
问题分析与解决
问题根源
你定义的MultipleFileType中,info被设置为固定长度的元组类型([{ fileName: string; file: File }]),TypeScript会默认认为这个数组只能有1个元素,因此推导出来的合法表单字段路径仅包含info.0.fileName、info.0.file这类固定值。当你动态生成info.${index}.fileName时,若index大于0,TypeScript会判定这些路径超出元组定义范围,从而抛出类型错误。
解决步骤
1. 修正类型定义(核心修复)
将info从固定元组改为动态数组类型,让TypeScript允许数组包含任意数量的元素:
interface MultipleFileType { info: { fileName: string; file: File; }[]; }
2. 用Zod自动推导类型(推荐,避免类型不一致)
直接从Zod Schema中自动生成类型,确保类型定义和验证规则完全对齐,无需手动维护:
import { z } from "zod"; const multipleSchema = z.object({ fileName: z.string({ required_error: "Name is required" }).min(5, { message: "Minimum length is 5" }), file: z .any() .refine((files) => files?.length == 1, 'Image is required.') .refine((files) => files?.[0]?.size <= (1024 * 1024 * 2.5), `Max file size is 2.5 MB.`) .refine( (files) => ['image/jpeg', 'image/jpg', 'image/png'].includes(files?.[0]?.type), '.jpg, .jpeg, .png and .webp files are accepted.', ), }); export const multipleFileUploaderSchema = z.object({ info: z.array(multipleSchema) }); // 从Schema自动推导类型 type MultipleFileType = z.infer<typeof multipleFileUploaderSchema>;
3. 确保字段名类型兼容
如果动态生成的字段名仍有类型报错,可以用Path类型辅助断言:
import { Path } from "react-hook-form"; // 在FormField的name属性中添加断言 name: `info.${index}.fileName` as Path<MultipleFileType>
4. 优化表单追加逻辑
调整append的初始值,让空状态更合理:
append({ fileName: "", file: new File([], "") // 空文件对象作为初始值 })
5. 可选:修正文件上传类型对齐
当前Zod验证针对FileList,但如果希望字段存储单个File对象,可以调整逻辑:
// 调整文件输入的onChange onChange((event) => { onChange(event.target.files?.[0]); // 传入单个File }); // 同步修改Zod Schema file: z .instanceof(File) .refine((file) => file.size <= (1024 * 1024 * 2.5), `Max file size is 2.5 MB.`) .refine( (file) => ['image/jpeg', 'image/jpg', 'image/png'].includes(file.type), '.jpg, .jpeg, .png and .webp files are accepted.', )
内容的提问来源于stack exchange,提问作者mustangDC
相关产品推荐
相关产品推荐

