10

Can a typescript type be used in a yup validation?

In yup you can:

yup.string().oneOf(['salami', 'tuna', 'cheese']);

In one of my components I have this type defined:

type toppings = 'salami' | 'tuna' | 'cheese';

Can I combine these two? I.e.:

type toppings = 'salami' | 'tuna' | 'cheese';
yup.string().oneOf(toppings); // <- how?
Remi
  • 4,663
  • 11
  • 49
  • 84

2 Answers2

14

You can use yup.mixed<TYPE>() passing your generic type.

yup.mixed<toppings>().oneOf(['salami', 'tuna', 'cheese']);

You are passing it as yup.string(), but it isn't a string, it's the type of 'salami' | 'tuna' | 'cheese', which contain string but isn't any string, so you need to use .mixed to define a specific value.

If you don't want to pass directly the array with the type values, you can take a look at this question on how to make it.

Vencovsky
  • 28,550
  • 17
  • 109
  • 176
  • Interesting. However, this gives me the error: `'toppingss only refers to a type, but is being used as a value here.ts(2693)` on the `.oneOf(toppings)` part. – Remi Sep 24 '20 at 12:16
  • @Remi now it's fixed, sorry for that. Please take a look at my edit – Vencovsky Sep 24 '20 at 12:18
  • Thanks, no worries. But still I'd have to manually define the values 'salami', 'tuna', 'cheese'. Isn't it possible to get that information from the alias? Since they're already defined there – Remi Sep 24 '20 at 12:20
  • @Remi I add how to do that in my answer, just take a look at linked question. You will have to convert the type into a enum and create a function to get the information – Vencovsky Sep 24 '20 at 12:20
  • Ah a getEnumValues. Tried that one out and found out the function actually wasn't correct and had some typing issues. Tried this one instead: https://stackoverflow.com/questions/50227229/typescript-infer-enum-value-type-from-enum-type. Do you want me to update your answer with a full example or provide a new one? – Remi Sep 24 '20 at 12:46
  • @Remi If you want too, you can, but I think it's better to leave the link to the other question, otherwise my answer will just be a copy of someone else's answer – Vencovsky Sep 24 '20 at 12:48
8

To build on @Vencovsky's answer a bit, you can use a const assertion if you want to avoid converting the type to an enum.

const possibleToppings = ['salami', 'tuna', 'cheese'] as const;

type toppings = typeof possibleToppings[number]; // 'salami' | 'tuna' | 'cheese'

yup.mixed<toppings>().oneOf([...possibleToppings]);
caseyjhol
  • 3,090
  • 2
  • 19
  • 23