Ошибка назначения типа в массиве объекта: машинописный текст, динамические формы с использованием пользовательского интерфейса Shadcn, форма перехвата React и ZOD

Я пытаюсь принять два поля [{fileName: string, file: File}] в динамической форме Typescript на основе React, где пользователь может добавить несколько наборов полей [{fileName: string, file: File}] при успешной проверке ZOD. Ниже приведены коды:

Тип:

interface MultipleFileType {
    info: [{
        fileName: string;
        file: File
    }]
}

Схема проверки

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
    )
})

Форма:

<Form {...form}>
 <form onSubmit = {form.handleSubmit(onSubmit)} className = "space-y-6">
  {fields.map((item, index) => (
   <div key = {item.id}>
    <div className = "md:flex md:flex-col">
     <FormField
      key = {index}
      control = {form.control}
      name = {`info.${index}.fileName`} <------- ERROR 1
      render = {({ field }) => (
       <FormItem>
        <FormLabel>Filename</FormLabel>
        <FormControl>
         <Input type = "text" {...field} />
        </FormControl>
        <FormMessage />
       </FormItem>
      )}
     />
    </div>
    <div className = "md:flex md:flex-col">
     <FormField
      key = {index}
      control = {form.control}
      name = {`info.${index}.file`} <------- ERROR 2
      render = {({ field: { onChange, ...fieldProps } }) => (
       <FormItem>
        <FormLabel>Picture</FormLabel>
        <FormControl>
         <input
          type = "file"
          {...fieldProps}
          value = {""}
          onChange = {(event) => {
           const { files } = getImageData(event, index);
           // setPreviewUrl(displayUrl);
           onChange(files);
          }}
          ref = {imgInputRef}
          hidden
         />
        </FormControl>
        {/* <FormMessage /> */}
       </FormItem>
      )}
     />
    </div>
    <Button
     disabled = {fields.length === 1}
     className = "text-red-500"
     variant = "outline"
     size = "icon"
     type = "button"
     onClick = {() => remove(index)}
    >
     <Trash className = "h-4 w-4" />
    </Button>
    <Button
     disabled = {fields.length > 2.5 * 1024 * 1024 || !form.formState.isValid}
     className = "ml-4"
     variant = "outline"
     size = "icon"
     type = "button"
     onClick = {() =>
      append({
       fileName: "",
       file: new File([], "/vite.svg"),
      })
     }
    >
     <Plus className = "h-4 w-4" />
    </Button>
   </div>
  ))}
  <Button type = "submit" className = "ml-4">
   Submit
  </Button>
 </form>
</Form>;

Ошибка, возникшая в обеих маркировках ERROR 1 и ERROR 2, выглядит следующим образом: Type 'info.${number}.fileName' is not assignable to type '"info" | "info.0" | "info.0.fileName" | "info.0.file"'.ts(2322) controller.d.ts(20, 5): The expected type comes from property 'name' which is declared here on type 'IntrinsicAttributes & { render: ({ field, fieldState, formState, }: { field: ControllerRenderProps<MultipleFileType, "info" | "info.0" | "info.0.fileName" | "info.0.file">; fieldState: ControllerFieldState; formState: UseFormStateReturn<...>; }) => ReactElement<...>; } & UseControllerProps<...>'

Любые предложения помогут.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
0
72
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы всегда можете преобразовать эти свойства имени в тип Path<z.infer<typeof yourSchemaHere>>, где Path экспортируется из формы реагирования, хотя способ структурирования ваших типов вы сообщаете машинописному сценарию, что длина массива всегда будет равна 1, и с кодом которым вы поделились, трудно сказать, тот ли это индекс, который вы сопоставляете. Если вы не хотите, чтобы длина этого массива всегда была равна 1, измените это:

interface MultipleFileType {
    info: [{
        fileName: string;
        file: File
    }]
}
export const multipleFileUploaderSchema = z.object({
    info: z.array(
        multipleSchema
    )
})

к этому:

interface MultipleFileType {
    info: {
        fileName: string;
        file: File
    }[]
}
export const multipleFileUploaderSchema = z.object({
    info: multipleSchema.array()
})

Это сработало!!! Это было несоответствие типа объявления массива.

mustangDC 27.06.2024 13:02

Другие вопросы по теме