T
TanStack4w ago
wise-white

How to use a Set in default values?

I am using Select from Hero UI, which uses a Set for its value. But when I do this, the schema validator types do not come out correctly. It seems they are transforming the types to be serializable, converting from Set to Array. Here's a mini code snippet to reproduce:
import {Schema} from "effect";

export const CreateScheduleInputSchema = Schema.Struct({
daysOfWeek: Schema.Set(Schema.Enums(DayOfWeek)).pipe(Schema.mutable),
});

const form = useAppForm({
defaultValues: {
daysOfWeek: new Set(),
},
validators: {
// The types are wrong here!
onSubmit: Schema.standardSchemaV1(CreateScheduleInputSchema),
},
});
import {Schema} from "effect";

export const CreateScheduleInputSchema = Schema.Struct({
daysOfWeek: Schema.Set(Schema.Enums(DayOfWeek)).pipe(Schema.mutable),
});

const form = useAppForm({
defaultValues: {
daysOfWeek: new Set(),
},
validators: {
// The types are wrong here!
onSubmit: Schema.standardSchemaV1(CreateScheduleInputSchema),
},
});
Is there something I am missing?
11 Replies
wise-white
wise-whiteOP4w ago
Here's the error
wise-white
wise-whiteOP4w ago
wise-white
wise-whiteOP4w ago
One way I solved this is to control the type so only arrays are set on the form instead of sets
export function FormSelect<T extends object>(props: SelectProps<T>) {
const field = useFieldContext<SharedSelection | string | number>();
const isInvalid = !field.state.meta.isValid;

return (
<Select<T>
name={field.name}
onBlur={field.handleBlur}
errorMessage={field.state.meta.errors?.[0]?.message}
isInvalid={isInvalid}
{...props}
/>
);
}

export function FormSelectSingle<T extends object>(props: SelectProps<T>) {
const field = useFieldContext<string | number>();

return (
<FormSelect<T>
selectionMode="single"
selectedKeys={new Set([field.state.value])}
onSelectionChange={(value) => field.handleChange([...value][0])}
{...props}
/>
);
}

export function FormSelectMultiple<T extends object>(props: SelectProps<T>) {
const field = useFieldContext<Array<string | number>>();

return (
<FormSelect<T>
selectionMode="multiple"
selectedKeys={new Set(field.state.value)}
onSelectionChange={(value) => field.handleChange([...value])}
{...props}
/>
);
}
export function FormSelect<T extends object>(props: SelectProps<T>) {
const field = useFieldContext<SharedSelection | string | number>();
const isInvalid = !field.state.meta.isValid;

return (
<Select<T>
name={field.name}
onBlur={field.handleBlur}
errorMessage={field.state.meta.errors?.[0]?.message}
isInvalid={isInvalid}
{...props}
/>
);
}

export function FormSelectSingle<T extends object>(props: SelectProps<T>) {
const field = useFieldContext<string | number>();

return (
<FormSelect<T>
selectionMode="single"
selectedKeys={new Set([field.state.value])}
onSelectionChange={(value) => field.handleChange([...value][0])}
{...props}
/>
);
}

export function FormSelectMultiple<T extends object>(props: SelectProps<T>) {
const field = useFieldContext<Array<string | number>>();

return (
<FormSelect<T>
selectionMode="multiple"
selectedKeys={new Set(field.state.value)}
onSelectionChange={(value) => field.handleChange([...value])}
{...props}
/>
);
}
import {Schema} from "effect";

export const CreateScheduleInputSchema = Schema.Struct({
daysOfWeek: Schema.Set(Schema.Enums(DayOfWeek)).pipe(Schema.mutable),
});

export type CreateScheduleInputSchema = typeof CreateScheduleInputSchema.Type;

const form = useAppForm({
defaultValues: {
daysOfWeek: [],
} as CreateScheduleInputSchema,
validators: {
// The types are wrong here!
onSubmit: Schema.standardSchemaV1(CreateScheduleInputSchema),
},
});
import {Schema} from "effect";

export const CreateScheduleInputSchema = Schema.Struct({
daysOfWeek: Schema.Set(Schema.Enums(DayOfWeek)).pipe(Schema.mutable),
});

export type CreateScheduleInputSchema = typeof CreateScheduleInputSchema.Type;

const form = useAppForm({
defaultValues: {
daysOfWeek: [],
} as CreateScheduleInputSchema,
validators: {
// The types are wrong here!
onSubmit: Schema.standardSchemaV1(CreateScheduleInputSchema),
},
});
flat-fuchsia
flat-fuchsia4w ago
does the schema allow you to view its input type? the standard schema spec requires them to be around, but I don‘t know the syntax to get them for this library
wise-white
wise-whiteOP4w ago
Yeah, that's done through what I have above
typeof CreateScheduleInputSchema.Type
typeof CreateScheduleInputSchema.Type
flat-fuchsia
flat-fuchsia4w ago
So if you write
const defaultValues: ThatInputType = { /* ... */ }
const defaultValues: ThatInputType = { /* ... */ }
what errors does it say it has with your previous stuff? Is it compatible?
wise-white
wise-whiteOP4w ago
That's the same as the type cast I have above:
defaultValues: {
daysOfWeek: [],
} as CreateScheduleInputSchema,
defaultValues: {
daysOfWeek: [],
} as CreateScheduleInputSchema,
flat-fuchsia
flat-fuchsia4w ago
a type cast is just that: a cast. It expects you to know for sure that it's compatible, which isn't type safe. The code I sent instead checks whether it actually is the same or not
wise-white
wise-whiteOP4w ago
Ah, right. Here's a minimal reproduction:
export const TestSchema = Schema.Struct({
aSet: Schema.Set(Schema.Enums(DayOfWeek)).pipe(Schema.mutable),
});

type TestSchema = typeof TestSchema.Type;

const testDefaultValues: TestSchema = {
aSet: new Set(),
};

function TestComponent() {
const form = useAppForm({
defaultValues: testDefaultValues,
validators: {
// Types fail here!
onSubmit: Schema.standardSchemaV1(TestSchema),
},
onSubmit: async ({ value }) => {
const decodedValue = Schema.decodeUnknownSync(TestSchema)(value);
console.log(decodedValue);
},
});
}
export const TestSchema = Schema.Struct({
aSet: Schema.Set(Schema.Enums(DayOfWeek)).pipe(Schema.mutable),
});

type TestSchema = typeof TestSchema.Type;

const testDefaultValues: TestSchema = {
aSet: new Set(),
};

function TestComponent() {
const form = useAppForm({
defaultValues: testDefaultValues,
validators: {
// Types fail here!
onSubmit: Schema.standardSchemaV1(TestSchema),
},
onSubmit: async ({ value }) => {
const decodedValue = Schema.decodeUnknownSync(TestSchema)(value);
console.log(decodedValue);
},
});
}
wise-white
wise-whiteOP4w ago
flat-fuchsia
flat-fuchsia4w ago
yeah, so it looks like the schema spec expects to receive an array and not a set. Weird how the spec would change that?

Did you find this page helpful?