diff --git a/src/__tests__/createSchemaForm.test.tsx b/src/__tests__/createSchemaForm.test.tsx index d2ae9db..069f838 100644 --- a/src/__tests__/createSchemaForm.test.tsx +++ b/src/__tests__/createSchemaForm.test.tsx @@ -1593,4 +1593,91 @@ describe("createSchemaForm", () => { numberArray: [1, 2, 3], }); }); + it("should render an array component with objects, and should map nonempty()", async () => { + const mockOnSubmit = jest.fn(() => {}); + const objectSchema = z.object({ + text: z.string(), + numberField: z.number(), + }); + function DynamicArray(_props: { something?: boolean }) { + const { + field: { value, onChange }, + } = useTsController[]>(); + + return ( +
+ + {value?.map((val, i) => { + return ( + + onChange( + value?.map((v, j) => + i === j ? { ...v, text: e.target.value } : v + ) + ) + } + /> + ); + })} +
+ ); + } + + function NumberField() { + return
number
; + } + + const mapping = [ + [objectSchema.array(), DynamicArray], + [z.number(), NumberField], + ] as const; + + const Form = createTsForm(mapping); + + const schema = z.object({ + arrayField: objectSchema.array().nonempty(), + numberArray: z.number().array(), + }); + const defaultValues = { + arrayField: [ + { text: "name", numberField: 2 }, + { text: "name2", numberField: 2 }, + ], + numberArray: [1, 2, 3], + }; + render( +
{ + return ; + }} + >
+ ); + + const numberNodes = screen.queryAllByText("number"); + numberNodes.forEach((node) => expect(node).toBeInTheDocument()); + expect(numberNodes).toHaveLength(3); + + expect(screen.getByTestId("dynamic-array")).toBeInTheDocument(); + const addElementButton = screen.getByTestId("add-element"); + await userEvent.click(addElementButton); + + const inputs = screen.getAllByTestId(/dynamic-array-input/); + expect(inputs.length).toBe(3); + }); }); diff --git a/src/unwrap.tsx b/src/unwrap.tsx index 54d5f7a..f7f5d36 100644 --- a/src/unwrap.tsx +++ b/src/unwrap.tsx @@ -1,5 +1,6 @@ import { z, + ZodArray, ZodEnum, ZodFirstPartyTypeKind, ZodNullable, @@ -78,12 +79,18 @@ export function unwrapEffects(effects: RTFSupportedZodTypes) { */ export type UnwrapZodType = T extends ZodOptional - ? EnumAsAnyEnum + ? GenericizeLeafTypes : T extends ZodNullable ? T["_def"]["innerType"] extends ZodOptional - ? EnumAsAnyEnum - : EnumAsAnyEnum - : EnumAsAnyEnum; + ? GenericizeLeafTypes + : GenericizeLeafTypes + : GenericizeLeafTypes; + +export type GenericizeLeafTypes = + ArrayAsLengthAgnostic>; + +export type ArrayAsLengthAgnostic = + T extends ZodArray ? ZodArray : T; export type EnumAsAnyEnum = T extends ZodEnum ? ZodEnum : T;