mSetAtPath

mSetAtPath

  • (path: PropertyKey[], value: any) => (anything: any) => anything
  1. Set a deep property

    const obj = {
      a: {
        b: 'c',
      },
    }
    const setBToD = mSetAtPath(['a', 'b'], 'd')
    const mutatedObj = setBToD(obj)
    
    console.log(mutatedObj === obj) // is true
    console.log(obj)
    // is {
    //   a: {
    //     b: 'd'
    //   }
    // }
    const obj = {
      a: {
        b: 'c',
      },
    }
    const setBToD = mSetAtPath(['a', 'b'], 'd')
    const mutatedObj = setBToD(obj)
    
    console.log(mutatedObj === obj) // is true
    console.log(obj)
    // is {
    //   a: {
    //     b: 'd'
    //   }
    // }
    
    const obj = {
      a: {
        b: 'c',
      },
    }
    const setBToD = mSetAtPath(['a', 'b'], 'd')
    const mutatedObj = setBToD(obj)
    
    console.log(mutatedObj === obj) // is true
    console.log(obj)
    // is {
    //   a: {
    //     b: 'd'
    //   }
    // }
    const obj = {
      a: {
        b: 'c',
      },
    }
    const setBToD = mSetAtPath(['a', 'b'], 'd')
    const mutatedObj = setBToD(obj)
    
    console.log(mutatedObj === obj) // is true
    console.log(obj)
    // is {
    //   a: {
    //     b: 'd'
    //   }
    // }
    
  2. Sometimes we want to set a deep property. Below, we built a website allowing users to choose between light and dark modes. Let's set the account preference to dark.

    const account = {
      email: 'meg@example.com',
      preferences: {
        mode: 'light',
      },
    }
    
    const setDarkMode = mSetAtPath(['preferences', 'mode'], 'dark')
    setDarkMode(account)
    
    console.log(account)
    // is {
    //   email: meg@example.com
    //   preferences: {
    //     mode: dark
    //   }
    // }
    type Account = {
      email: string
      preferences: { mode: string }
    }
    const account: Account = {
      email: 'meg@example.com',
      preferences: {
        mode: 'light',
      },
    }
    
    const setDarkMode = mSetAtPath(['preferences', 'mode'], 'dark')<Account>
    setDarkMode(account)
    
    console.log(account)
    // is {
    //   email: meg@example.com
    //   preferences: {
    //     mode: dark
    //   }
    // }
    
    const account = {
      email: 'meg@example.com',
      preferences: {
        mode: 'light',
      },
    }
    
    const setDarkMode = mSetAtPath(
      ['preferences', 'mode'],
      'dark'
    )
    setDarkMode(account)
    
    console.log(account)
    // is {
    //   email: meg@example.com
    //   preferences: {
    //     mode: dark
    //   }
    // }
    type Account = {
      email: string
      preferences: { mode: string }
    }
    const account: Account = {
      email: 'meg@example.com',
      preferences: {
        mode: 'light',
      },
    }
    
    const setDarkMode = mSetAtPath(
      ['preferences', 'mode'],
      'dark'
    )<Account>
    setDarkMode(account)
    
    console.log(account)
    // is {
    //   email: meg@example.com
    //   preferences: {
    //     mode: dark
    //   }
    // }
    
  3. This utility has a few requirements

    • Path must have at least one element
    • Path must exist on the object and be assignable

    The example shows the errors thrown for each requirement

    try {
      mSetAtPath([], 'path cannot be empty')
    } catch (err) {
      console.log(err)
      // prints
      // mSetAtPath requries 'path' to be a non-empty array
    }
    
    const setBToD = mSetAtPath(['a', 'b'], 'd')
    
    try {
      const noA = {}
      setBToD(noA)
    } catch (err) {
      console.log('\n', err)
      // prints
      // mSetAtPath requires path to exist on 'anything'.  Arguments are assigned to
      // this error to aid in debugging.
    }
    
    try {
      const bIsUnassignable = { a: "can't assign a property to primitive" }
      setBToD(bIsUnassignable)
    } catch (err) {
      console.log('\n', err)
      // prints
      // mSetAtPath requires the property at path to be assignable.  See error
      // properties for more info.
    }
    try {
      mSetAtPath([], 'path cannot be empty')
    } catch (err) {
      console.log(err)
      // prints
      // mSetAtPath requries 'path' to be a non-empty array
    }
    
    const setBToD = mSetAtPath(['a', 'b'], 'd')
    
    try {
      const noA = {}
      setBToD(noA)
    } catch (err) {
      console.log('\n', err)
      // prints
      // mSetAtPath requires path to exist on 'anything'.  Arguments are assigned to
      // this error to aid in debugging.
    }
    
    try {
      const bIsUnassignable = { a: "can't assign a property to primitive" }
      setBToD(bIsUnassignable)
    } catch (err) {
      console.log('\n', err)
      // prints
      // mSetAtPath requires the property at path to be assignable.  See error
      // properties for more info.
    }
    
    try {
      mSetAtPath([], 'path cannot be empty')
    } catch (err) {
      console.log(err)
      // prints
      // mSetAtPath requries 'path' to be a non-empty
      // array
    }
    
    const setBToD = mSetAtPath(['a', 'b'], 'd')
    
    try {
      const noA = {}
      setBToD(noA)
    } catch (err) {
      console.log('\n', err)
      // prints
      // mSetAtPath requires path to exist on
      // 'anything'.  Arguments are assigned to this
      // error to aid in debugging.
    }
    
    try {
      const bIsUnassignable = {
        a: "can't assign a property to primitive",
      }
      setBToD(bIsUnassignable)
    } catch (err) {
      console.log('\n', err)
      // prints
      // mSetAtPath requires the property at path to
      // be assignable.  See error properties for
      // more info.
    }
    try {
      mSetAtPath([], 'path cannot be empty')
    } catch (err) {
      console.log(err)
      // prints
      // mSetAtPath requries 'path' to be a non-empty
      // array
    }
    
    const setBToD = mSetAtPath(['a', 'b'], 'd')
    
    try {
      const noA = {}
      setBToD(noA)
    } catch (err) {
      console.log('\n', err)
      // prints
      // mSetAtPath requires path to exist on
      // 'anything'.  Arguments are assigned to this
      // error to aid in debugging.
    }
    
    try {
      const bIsUnassignable = {
        a: "can't assign a property to primitive",
      }
      setBToD(bIsUnassignable)
    } catch (err) {
      console.log('\n', err)
      // prints
      // mSetAtPath requires the property at path to
      // be assignable.  See error properties for
      // more info.
    }