Can we avoid .nonempty() changing the inferred input type? #3040
-
Take below example: import { z } from 'zod';
const schema = z.number().array().nonempty();
// expected type to be number[], but instead is [number, ...number[]]
type inputType = z.input<typeof schema>;
// simplified for demo
const formValidation: (userInput: inputType) => boolean = (userInput) => {
// ....
return true;
};
// user input of either correct array or incorrect empty array...
const formData: number[] = Math.random() % 2 ? [2] : [];
// this should typecheck, but doesn't because the .nonemtpy() call pollutes the inferred input type.
const isValid = formValidation(formData); Is this a bug? or intentional? I can imagine zod being intentionally like this, as this behaviour is the one that utilises TS to the limit, but I would expect that this is the opposite of what the usual use case would demand. Is there some elegant solution to this, that doesn't involve breaking typesafety with multiple schema definitions and/or forced casts especially when the array is actually in a nested zod object schema, so I can't easily just create a simple and a chained .nonemtpy variant? |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 1 reply
-
TypeScript is doing what it's supposed to do here: const schema = z.number().array().nonempty()
type NonEmptyArray = z.input<typeof schema>
// type NonEmptyArray = [number, ...number[]]
const foo = ( x: NonEmptyArray ) => { }
foo( [ 42 ] ) // ok
foo( [] )
// ^^
// Argument of type '[]' is not assignable to parameter of type '[number, ...number[]]'.
// Source has 0 element(s) but target requires 1. If you truly want a compile time non empty array, then this is correct. But it seems you don't want your types to match your runtime values. Is that correct? |
Beta Was this translation helpful? Give feedback.
-
Note that I am talking about What I am surprised by is that Since then I realized that I can easily achieve what I need with using |
Beta Was this translation helpful? Give feedback.
-
i found this https://github.com/causaly/zod-non-empty-array/ |
Beta Was this translation helpful? Give feedback.
TypeScript is doing what it's supposed to do here:
If you truly want a compile time non empty array, then this is correct. But it seems you don't want your types to match your runtime values. Is that correct?