david-plugge / typed-formdata

MIT License
3 stars 1 forks source link

Typescript showing error in input name attribute when zod schema has optional string properties with validation #6

Closed Josh-Nicholson closed 1 year ago

Josh-Nicholson commented 1 year ago

I'm having an issue with TypeScript detecting an issue in my input name attributes when I'm trying to use optional string properties within my zod schemas/

My schema looks like this:

export const customerInfoDto = z.object({
    companyId: z.string(),
    name: z.string(),
    addresses: z.array(z.object({
        id: z.string().uuid(),
        name: z
            .string({ required_error: 'Name is required' })
            .min(2, { message: 'Name must be at least 2 characters' })
            .max(256, { message: 'Name must be 256 characters or less' }),
        address1: z
            .string({ required_error: 'Address 1 is required' })
            .min(2, { message: 'Address 1 must be at least 2 characters' })
            .max(256, { message: 'Address 1 must be 256 characters or less' }),
        address2: z.string().max(256, { message: 'Address 2 must be 256 characters or less' }).optional().or(z.literal('')),
        address3: z.string().max(256, { message: 'Address 3 must be 256 characters or less' }).optional().or(z.literal('')),
        address4: z.string().max(256, { message: 'Address 4 must be 256 characters or less' }).optional().or(z.literal('')),
    }))
});

On my form I use the code snippet from your sveltekit example: const customerInfo = formFields<typeof customerInfoDto>();

which calls:

export function formFields<T extends z.Schema>() {
    return fields<z.infer<T>>();
}

This is how I display the properties within the addresses array.

{#each data.customer?.addresses as address, i}
  <label class="label">
      <span>Name</span>
      <input
          class="input"
          type="text"
          name={customerInfo.addresses(i).name}
          placeholder="Address Name"
          value={data.customer?.addresses[i].name}
      />
  </label>
  <label class="label">
      <span>Address 1</span>
      <input
          class="input"
          type="text"
          name={customerInfo.addresses(i).address1}
          placeholder="Address 1"
          value={data.customer?.addresses[i].address1}
      />
  </label>
  <label class="label">
      <span>Address 2</span>
      <input
          class="input"
          type="text"
          name={customerInfo.addresses(i).address2}
          placeholder="Address 2"
          value={data.customer?.addresses[i].address2}
      />
  </label>
{/each}

The name attribute works for the properties Name and Address1, but not for Address2 I get the following error: image

Any help would be greatly appreciated.

david-plugge commented 1 year ago

Interesting. The DeepRequired type didnt work for nested arrays. Let me know if it´s fixed for you in the latest version.

Josh-Nicholson commented 1 year ago

Thanks for such a quick response. After updating to the latest version, it appears to now be working :)