2

I am trying to add new element inside a React object, but I am getting below issue

const isAdmin = true
let schema = {
            fname: Yup.string().required('Required'),
            lname: Yup.string().required('Required'),
            ...(isAdmin && isFirstLogin) && {role: Yup.string()},
    };

It's working fine when isAdmin = true. But whenever I am doing isAdmin = false its showing me error like:

Spread types may only be created from object types.

Why does it not work with false?

2
  • is isFirstLogin also a boolean? Commented Mar 11, 2021 at 8:39
  • @hellogoodnight truthy/falsey would still work there with isFirstLogin, but being prefixed with is I would expect it to a boolean type. Commented Mar 11, 2021 at 8:41

1 Answer 1

1

Issue

With ...(isAdmin && isFirstLogin) && {role: Yup.string()} when isAdmin is false, then (isAdmin && isFirstLogin) evaluates to false. When this happens the rest of the boolean expression is ignored from the way javascript shortcuts out of evaluating the expression. It's at this point you are attempting to spread false into the schema but this fails since it isn't iterable.

Solution

You need to handle the "unhappy" false path by still providing a value that can be spread. Using a ternary allows you to test the isAdmin && isFirstLogin condition and return { role: Yup.string() } if true, and a spreadable empty object {} if false.

const isAdmin = true
let schema = {
  fname: Yup.string().required('Required'),
  lname: Yup.string().required('Required'),
  ...(isAdmin && isFirstLogin) ? { role: Yup.string() } : {},
};

const isFirstLogin = true;

const schema1 = {
  fname: 'first',
  lname: 'last',
  ...(true && isFirstLogin) ? { role: 'role' } : {},
};

const schema2 = {
  fname: 'first',
  lname: 'last',
  ...(false && isFirstLogin) ? { role: 'role' } : {},
};

const schema3 = {
  fname: 'first',
  lname: 'last',
  ...(true && false) ? { role: 'role' } : {},
};

console.log(schema1, schema2, schema3);

Sign up to request clarification or add additional context in comments.

2 Comments

This does not change anything. The problem is that he is trying to spread the boolean value false. It must be the case that "isFirstLogin" is a spreadable element, i.e. not a boolean.
@hellogoodnight Incorrect, everything in the () is evaluated before anything is possibly spread, i.e. (isAdmin && isFirstLogin) is evaluated before the rest of the line is. It's when (isAdmin && isFirstLogin) evaluated to false that false was attempted to be spread, and failed. This is why switching to a ternary and providing an empty object ({}) works and is spreadable. Check the stacksnippet I added.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.