Error encountered when assigning types in an array of objects: Working with Typescript, Dynamic Forms utilizing Shadcn UI, React Hook Form, and ZOD

I am currently working on implementing a React-based Typescript Dynamic form that allows users to input two fields [{fileName: string, file: File}]. Users should be able to add multiple sets of these fields [{fileName: string, file: File}] upon successful ZOD validation. Below you can find the relevant code snippets:

Data Type:

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

Validation Schema:

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 Structure:

<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>;

The issue marked as ERROR 1 and ERROR 2 in the code snippet is as follows: 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<...>'

Any suggestions or feedback would be greatly appreciated.

Answer №1

If you want to ensure that your array does not always have a length of 1, you can cast the name properties to a

Path<z.infer<typeof yourSchemaHere>>
type. The Path is exported from react-hook-form. However, based on how your types are structured in typescript, it may appear that you're indicating the array will consistently have a length of 1. It's unclear from the code provided if this aligns with the index being mapped over.

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

To adjust this behavior and allow for varying array lengths, update the structure as follows:

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

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is there a way to retrieve the quantity of children from an element using protractor?

I am currently working with Protractor and I need to determine the amount of child components associated with a specific element. The element in question belongs to a table category. let table = element(by.css('#myTable')); My objective now is ...

Error: Promise was not caught - The request to the URL returned an unauthorized status code of 401

https://i.sstatic.net/9lewp.pngImplementing authGuard for my Routers has been a challenge. Whenever I try to handle error codes, it ends up breaking the entire application. I'm currently at a loss on how to resolve this issue and would greatly appreci ...

Errors in Intellisense detected within the latest Node Tools Express App development project

After setting up a new project with the "Basic Node.js Express 4 Application" template, I noticed some errors have already surfaced: https://i.sstatic.net/8jbYt.png Could this be a Visual Studio issue? Any pointers on resolving these errors? ...

What is the process for creating a linked TreeNode in the Ant tree design?

After completing a tree design utilizing Ant Design, I encountered an issue where certain nodes within the tree needed to act as links. Despite my attempts to directly assign links, they were not functioning properly. array.map((node) => { if(node.t ...

What is the purpose of utilizing import and require() in Node.js programming?

Currently, I am analyzing the source code found at "Type definitions for Express 4.16" and stumbled upon this interesting line (#18): import serveStatic = require("serve-static"); I couldn't help but wonder why the above code is necessary or being u ...

Where can the body of this function be located in Typescript and do the generics serve a practical purpose?

While perusing the documentation for Angular's "AsyncPipe", I found myself at a standstill on line 26, where the 'resolve' function is invoked: this.resolve !('hi there!'); I have some questions on my mind: (A) Where is the impl ...

The "Icon and Expanded Icon Style" feature of NativeBase is failing to display

I am brand new to this and I seem to have missed something during the installation process. My inquiry revolves around why the icons are not displaying when I follow the simple code copied from nativebase.io. The build is successful, all functions work, b ...

Steps for embedding a camera within a group using react three fiber

I'm struggling to figure out how to achieve this in react-three-fiber. My goal is to set up a rig for a camera, which is simple to do in three.js. I place the camera inside a group. When I want to rotate the camera around the Y axis, I adjust the rota ...

Resetting all form fields in React components

Encountering an issue with my react application. When filling out the Last Name field and then opening the "Address Dialog" to enter an address, everything works fine. However, the problem arises when I've already entered the Last Name and then procee ...

Issue with Alignment of Border in PDF [Example Included]

I am currently developing a straightforward react application with very minimal content. index.js: <div className="App"> <div id="printable-div"> <h1>Generate PDF</h1> <p>Capture a screenshot of ...

Steer clear of repeatedly invoking functions in ReactJs

I have a function named calculations() that performs various calculations and returns multiple objects. The issue I'm facing is that within a component, I have to repeatedly call this function in order to access the returned objects, leading to code ...

The issue with JWT Authorization

I've encountered an issue with this code as it used to work fine before but for some reason, it's failing now. It seems like the problem lies in this particular part of the code. The error message displayed on the frontend is "Logging in failed, ...

When using Next JS with StoryBook, an error may occur if styles are written in a module.scss file

Every time I try to add some styles to my ButtonWidget.scss file, I encounter an error in the console when running the command yarn storybook Error Code: ERROR in ./src/components/ButtonWidget/ButtonWidget.module.scss 1:0 Module parse failed: Unexpected ...

Ways to conceal the primereact Calendar element

Is there a method to conceal the calendar using a custom button? <Calendar onHide={handleCalendarHide} />; Currently, I can only hide the calendar by clicking outside of it, which triggers the onHide event. However, I would like to hide the calendar ...

typescript, generate a new type by merging option values

In typescript I am faced with a challenge. I have a type called A: interface A { a1: string; a2: int; } As well as another type called B: interface B { b1: number } Now, my goal is to create a new type: interface AB { a1?: string; a2? ...

An unexpected token was discovered by Jest: export { default as v1 } when using uuid

While working on writing Jest tests for my React component in a Monorepo, I encountered an error while running the Jest test. ● Test suite failed to run Jest encountered an unexpected token... ...SyntaxError: Unexpected token 'export' ...

Facing a problem with NEXTJS api, axios, and NextAuth: AxiosError occurs due to connection being refused on ::1:3000

In my Next.js application, I am implementing NextAuth for authentication. To make API calls within the same app using axios, I need to specify the verify_url correctly. When I use "http://localhost:3000" in the verify_url and load the app in dev mode, ever ...

How can I bring in createRoot in React?

I am currently experimenting with React and came across an issue in my script. Even though I have imported 'createRoot' from 'react-dom/client', the browser console is still throwing a warning. The warning states that importing creat ...

Ways to stop dialog from disappearing in Reactjs

This code snippet demonstrates the implementation of a popup with buttons, where clicking the cancel button triggers a confirmation dialog. To make the popup disappear when clicked outside of it, the following event handling is employed: const popupRef = ...

Ways to incorporate design elements for transitioning focus between different elements

When focusing on an element, I am using spatialNavigation with the following code: in index.html <script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="dfb5acf2acafbeabb6beb3f2b1bea9b6 ...