Skip to content
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

How to implement a generic yup schema? #1942

Open
leandertolksdorf opened this issue Mar 13, 2023 · 1 comment
Open

How to implement a generic yup schema? #1942

leandertolksdorf opened this issue Mar 13, 2023 · 1 comment

Comments

@leandertolksdorf
Copy link

Assume I have the following defined:

export const flours = {
  Wheat: ["405", "550", "812", "1050", "Tipo 0", "Tipo 00", "Full-Grain"],
  Spelt: ["630", "812", "1050", "Full-Grain"],
  Rye: ["815", "997", "1150", "1370", "1740", "1800", "Full-Grain"],
  "Durum / Semola / Semolina": ["di Grano Duro Rimacinata"],
  Emmer: ["405", "630", "812", "1050", "1300", "Full-Grain"],
  Einkorn: ["405", "630", "812", "1050", "1300", "Full-Grain"],
} as const;

export interface IFlour {
  grain: keyof typeof flours;
  type: (typeof flours)[keyof typeof flours][number];
}

export const flourSchemaYup: ObjectSchema<IFlour> = object({
  grain: string<IFlour["grain"]>().required(),
  type: string<IFlour["type"]>().required(),
});

and a generic Interface IIngredient:

export interface IIngredient<T> {
  grams: number;
  ingredient: T;
}

How can I implement a dynamic yup schema that validates an IIngredient<T> with a dynamic T?

I've tried it like this:

// Throws a TypeError (see below)
export const ingredientSchemaYup = <T extends object>(
  ingredient: ObjectSchema<T>
): ObjectSchema<IIngredient<T>> =>
  object({
    grams: number().required(),
    ingredient: ingredient
  });

// Returns an ObjectSchema<IIngredient<IFlour>, ...>, as expected.
const flourIngredientSchemaYup = ingredientSchemaYup(flourSchemaYup);

TypeError:

TS2322: Type 'ObjectSchema<{ grams: number; ingredient: MakeKeysOptional<T>; }, AnyObject, { grams: undefined; ingredient: any; }, "">' is not assignable to type 'ObjectSchema<IIngredient<T>, AnyObject, any, "">'.   The types of 'default(...).fields.ingredient' are incompatible between these types.     Type 'Reference<unknown> | ISchema<MakeKeysOptional<T>, AnyObject, any, any>' is not assignable to type 'Reference<unknown> | ISchema<T, AnyObject, any, any>'.       Type 'ISchema<MakeKeysOptional<T>, AnyObject, any, any>' is not assignable to type 'Reference<unknown> | ISchema<T, AnyObject, any, any>'.         Type 'ISchema<MakeKeysOptional<T>, AnyObject, any, any>' is not assignable to type 'ISchema<T, AnyObject, any, any>'.           Type 'MakeKeysOptional<T>' is not assignable to type 'T'.             'MakeKeysOptional<T>' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'object'.               Type 'T | _<MakePartial<T>>' is not assignable to type 'T'.                 'T | _<MakePartial<T>>' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'object'.                   Type '_<MakePartial<T>>' is not assignable to type 'T'.                     '_<MakePartial<T>>' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'object'.                       Type 'MakePartial<T> | { [k in keyof MakePartial<T>]: MakePartial<T>[k]; }' is not assignable to type 'T'.                         'MakePartial<T> | { [k in keyof MakePartial<T>]: MakePartial<T>[k]; }' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'object'.                           Type 'MakePartial<T>' is not assignable to type 'T'.                             'MakePartial<T>' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'object'.                               Type '{}' is not assignable to type 'T'.                                 '{}' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'object'.
@falaxfala
Copy link

Got the same issue with react-hook-form
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants