valibot icon indicating copy to clipboard operation
valibot copied to clipboard

How to create dynamic variants with the nested schemas?

Open nd0ut opened this issue 6 months ago • 3 comments

Hello!

Here is the playground MRE: https://valibot.dev/playground/?code=JYWwDg9gTgLgBAKjgQwM5wG5wGZQiOAcg2QBtgAjCGQgbgCh6BjCAO1XgCUBTVAV1IwAykwAW3EMjgBeTADoIFAFbcmMABQBvenDgBrbgE8AXPI5RgrAObqAlABp6AX1sNmbDnCExkMYEwA1ZAtkVmExCSlZDDkSELD1Qn4mJl5UQns4AG0deUUVNS1c3WTU1FRTGPIYbigydWwyVG4HYrhavChKuUsOUNT1AFEoTtbdF0ddGPzVDW1dEr4UtO7q2vqYKD4WyYWoXgEYUx5+QRFxSV2J+gBdV0YWdngAEUNWZBB-IPjwi6i4AA8ABV2gAPGqsAAm6BiAHllLNzpEAaFDJlUQA+DHqXL7U6-SKmIGOWwyDG5GJxYChDRJJZldKZHILPIIwrzFlwUoreRrOqkBpNHZtXQdaDdXo+VgDYajXbjMYLaZsuYirn0nlVYA1fnqTbbRUsvGHUzGs4RS5ta66O4MIA

Inline code:

import * as v from 'valibot';

const ResultSchema = v.object({
  key: v.string(),
});

const StaticVariantSchema = v.variant('success', [
  v.object({
    success: v.literal(false),
    error: v.instance(Error),
  }),
  v.object({
    success: v.literal(true),
    result: ResultSchema,
  }),
]);

const DynamicVariantSchema = <T extends v.ObjectSchema<any, any>>(
  resultSchema: T,
) =>
  v.variant('success', [
    v.object({
      success: v.literal(false),
      error: v.instance(Error),
    }),
    // here i'm getting error
    v.object({
      success: v.literal(true),
      result: resultSchema,
    }),
  ]);

const staticResult = v.parse(StaticVariantSchema, {
  success: true,
  result: {
    key: 'string',
  },
});

const dynamicResult = v.parse(DynamicVariantSchema(ResultSchema), {
  success: true,
  result: {
    key: 'string',
  },
});

console.log(staticResult, dynamicResult);

At runtime, it's working OK, but I got an error from TS:

Type 'ObjectSchema<{ readonly success: LiteralSchema<true, undefined>; readonly result: S; }, undefined>' is not assignable to type 'VariantOption<"success">'.
  Type 'ObjectSchema<{ readonly success: LiteralSchema<true, undefined>; readonly result: S; }, undefined>' is not assignable to type 'ObjectSchema<Record<"success", BaseSchema<unknown, unknown, BaseIssue<unknown>>>, ErrorMessage<ObjectIssue> | undefined>'.
    The types returned by '_run(...)' are incompatible between these types.
      Type 'Dataset<{ [TKey in keyof WithReadonly<{ readonly success: LiteralSchema<true, undefined>; readonly result: S; }, WithQuestionMarks<{ readonly success: LiteralSchema<true, undefined>; readonly result: S; }, InferEntriesOutput<...>>>]: WithReadonly<...>[TKey]; }, ObjectIssue | InferObjectIssue<...>>' is not assignable to type 'Dataset<{ success: unknown; }, BaseIssue<unknown> | ObjectIssue>'.
        Type 'TypedDataset<{ [TKey in keyof WithReadonly<{ readonly success: LiteralSchema<true, undefined>; readonly result: S; }, WithQuestionMarks<{ readonly success: LiteralSchema<true, undefined>; readonly result: S; }, InferEntriesOutput<...>>>]: WithReadonly<...>[TKey]; }, ObjectIssue | InferObjectIssue<...>>' is not assignable to type 'Dataset<{ success: unknown; }, BaseIssue<unknown> | ObjectIssue>'.
          Type 'TypedDataset<{ [TKey in keyof WithReadonly<{ readonly success: LiteralSchema<true, undefined>; readonly result: S; }, WithQuestionMarks<{ readonly success: LiteralSchema<true, undefined>; readonly result: S; }, InferEntriesOutput<...>>>]: WithReadonly<...>[TKey]; }, ObjectIssue | InferObjectIssue<...>>' is not assignable to type 'TypedDataset<{ success: unknown; }, BaseIssue<unknown> | ObjectIssue>'.
            Property 'success' is missing in type '{ [TKey in keyof WithReadonly<{ readonly success: LiteralSchema<true, undefined>; readonly result: S; }, WithQuestionMarks<{ readonly success: LiteralSchema<true, undefined>; readonly result: S; }, InferEntriesOutput<...>>>]: WithReadonly<...>[TKey]; }' but required in type '{ success: unknown; }'.ts(2322)

Am I doing something wrong with the generics, or is it a bug?

nd0ut avatar Aug 01 '24 01:08 nd0ut