javascriptecmascript-6

How can I convert a complex if/ifelse/else condition to a readable Object Literal in JavaScript?


I rewrote my code to what I think I was trying to accomplish. I cannot wrap my head around using object literals as an alternative to if/else or switch. How would you convert the if/else condition to an Object Literal below?

let bobRes = "A123";
//stored password in database
let sPass = "A1234";
let qState = "q1";

function responseHandler(bobResValue, sPassValue, qStateValue) {
  if (sPass === "" && qStateValue === "q1") {

    return "Create a new password using five digits.";
  } else if (bobResValue.length !== 5 && qStateValue === "q1") {

    return "Password is too short!";
  } else if (bobResValue !== sPassValue) {

    return "Wrong Password";
  } else if (bobResValue === sPass) {

    return "Correct Password";
  } else {

    return "You must enter a password to continue?";
  }
}

let finalResponse = responseHandler(bobRes, sPass, qState);
console.log(finalResponse)

My attempt to convert to object literal! But I'm stuck on the logic...

let bobRes = "A123";
//stored password in database
let sPass = "A1234";
 


function responseHandler(bobResValue) {
  let respObj = {

    "None": "You must enter a password." 
   
  }
  let respObj2 = {
      passWordLength: (bobResValue) => bobResValue.length != 5,
  }

let respObj3 = {
      passWordLength: (bobResValue) => bobResValue === 5,
  }

  respObj[bobResValue] ?? respObj2[passWordLength]?? "You must enter a password to continue!";
}

let finalResponse = responseHandler(bobRes, sPass, qState);
console.log(finalResponse)


Solution

  • Don't give up! These kinds of refactors will teach you to identify problems with how you are thinking about the program and permanently unlock new techniques.

    This is a practical use case for the Either monad. Don't let unfamiliar terms scare you. Here we demonstrate the technique in a lo-fi way as ok and err. If you have any questions, just ask -

    const ok = value => ({
      chain: f => f(value),
      get: (ifOk, _) => ifOk(value)
    })
    
    const err = value => ({
      chain: _ => err(value),
      get: (_, ifErr) => ifErr(value)
    })
    
    const isEmpty = s => (s === "")
      ? err("create a new password using five digits")
      : ok(s)
    
    const isTooShort = s => (s.length != 5 || Number.isNaN(Number.parseInt(s)))
      ? err("password is not five digits")
      : ok(s)
    
    const isMatch = match => s => (s !== match)
      ? err("wrong password")
      : ok(s)
    
    function validate(pass, match) {
      return isEmpty(pass)
        .chain(isTooShort)
        .chain(isMatch(match))
        .get(console.log, console.error)
    }
    
    validate("", "foo")
    validate("123", "123")
    validate("12345", "9876")
    validate("12345", "12345")

    Replace console.log with the identity function, v => v, to have validate return the valid password instead of logging it to the console.

    Optionally replace console.error with msg => { throw Error(msg) } to have validate throw an error that corresponds to the specific failure.