-
-
Notifications
You must be signed in to change notification settings - Fork 220
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
using union
as key of record
adds undefined
to the value type
#492
Comments
This is the intended behavior when |
But please leave this issue open. I agree that it would be better to specify it as undefined only when |
How would I model the type |
I would use import * as v from 'valibot';
const Schema = v.object({ a: v.number(), b: v.number() }); But maybe you are right and our current typing and implementation is wrong and we should only mark it as optional when |
@bug-brain I investigated this issue further. It is true that the behavior of Valibot is different from TypeScript and it would be nice to unify it. But there is a tradeoff. To support this behavior, |
Since many Zod users are also complaining about this problem in #2623, I will investigate this further to find an appropriate solution. |
I think I fixed it! Will test and investigate my code tomorrow. Thanks for bringing this up! |
Even if I found a solution, I am not sure if we should go this way as a library focused on bundle size. Supporting this behavior increases the bundle size of // `record` does only allow `string` as first argument
const Schema1 = v.record(v.string(), v.number());
// For explicit keys, `object` with `entriesFrom` is used instead
const Schema2 = v.object(v.entriesFrom(['foo', 'bar'], v.number()));
// Or without the util function
const Schema2 = v.object({ foo: v.number(), bar: v.number() }); |
@fabian-hiller may I ask how much |
I am using a export const PosTypeEnumSchema = z.enum(['external', 'online', 'standard', 'telephone']); That way I don't need to define all of my enum schemas manually. Now I need a record with these enums as a key type and I don't want to re-define these keys by hand but instead use the generated |
The next version of Valibot will allow you to write the following code to solve your problem. Feel free to give me feedback on this in the long run. import * as v from 'valibot';
const ListSchema = v.picklist(['external', 'online', 'standard', 'telephone']);
const ObjectSchema = v.object(v.entriesFromList(ListSchema.options, v.number())); |
I am not a maintainer of Zod, so I cannot speak for it. I recommend asking the Zod team directly. |
Thank you, I'll do that :) |
This is now implemented and available. |
Good time! Sorry, but my opinion is that there is no need to come up with additional constructions, such as entriesFromList, when a similar utility from typescript contradicts the behavior of "record". No matter how difficult it may be, you need to try to do it correctly. import { InferOutput, number, picklist, pipe, record, string, transform } from 'valibot';
export const rows = [0, 1, 2, 3, 4] as const;
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument
export const isRow = (input: any): input is (typeof rows)[number] => rows.includes(input);
export const RowScheme = picklist(rows);
export type Row = InferOutput<typeof RowScheme>;
// type Rows = 0 | 1 | 2 | 3 | 4
/*
The input type for a "record" must be a string, although the output type can be a number or a symbol.
Therefore, you have to do redundant transformation.
*/
export const RowNumberSchema = pipe(
string(),
transform<string, (typeof rows)[number]>((input) => {
if (isRow(input)) return input;
throw new Error(`${input} cannot be assigned to rows`);
}),
);
// similar type to Row
export type RowNumber = InferOutput<typeof RowNumberSchema>;
// type RowsNumber = 0 | 1 | 2 | 3 | 4
export const RowOptionsSchema = record(RowNumberSchema, number());
export type RowOptions = InferOutput<typeof RowOptionsSchema>;
/*
type RowOptions = {
0?: number | undefined;
1?: number | undefined;
2?: number | undefined;
3?: number | undefined;
4?: number | undefined;
}
*/ |
I think we can extend it to numbers and symbols. I will investigate this.
This is an open source project. You are free to investigate the implementation and provide a proof of concept that aligns with our philosophy. If everything looks good, I will be happy to merge your changes. |
v0.36.0 is available |
Thank you very much for your promptness. Now this also works with numbers and symbols. |
The text was updated successfully, but these errors were encountered: