digitallinguistics/javascript

add internal utility to define an enumerable property

dwhieb opened this issue · 0 comments

/**
 * Adds a property to the provided object which may only have the specified values
 * @param  {Object} object       The object to add the property to
 * @param  {String} propName     The name of the property to add
 * @param  {Array}  values       An array of acceptable values for the new property
 * @param  {Any}    initialValue The initial value to give to the new property. Will be `undefined` if none is provided.
 * @return {Object}              Returns the original object with the new property added
 */
function defineEnumProp(object, propName, values, initialValue) {

  if (!(object instanceof Object)) {
    throw new TypeError(`The "object" argument must be an Object.`);
  }

  if (!Array.isArray(values)) {
    throw new TypeError(`The "values" argument must be an array of allowed values.`);
  }

  const o = object;

  let value;

  Object.defineProperty(o, propName, {
    configurable: true,
    enumerable:   true,
    get() { return value; },
    set(val) {

      if (!values.includes(val)) {
        throw new Error(`The value provided is not a valid value for the "${propName}" property.`);
      }

      value = val;

    },
  });

  if (typeof initialValue !== 'undefined') o[propName] = initialValue;

  return o;

}