docs: function defineGetter(index, properties) {
          // If the field type is an alias, we retrieve the value through the alias's index.
          let indexOrAliasIndex = properties.type === 'alias' ? properties.index : index;
  
          this.__defineGetter__(index, () => {
              // If accessing object or array, lazy initialize if not set.
              if (!this[_privateKey]._obj[indexOrAliasIndex] && (properties.type === 'object' || properties.type === 'array')) {
                  // Initialize object.
                  if (properties.type === 'object') {
                      if (properties.default !== undefined) {
                          writeValue.call(this[_privateKey]._this, _.isFunction(properties.default) ?
                              properties.default.call(this) :
                              properties.default, properties);
                      } else {
                          writeValue.call(this[_privateKey]._this,
                              properties.objectType ? new properties.objectType({}, this[_privateKey]._root) : {}, properties);
                      }
  
                      // Native arrays are not used so that Array class can be extended with custom behaviors.
                  } else if (properties.type === 'array') {
                      writeValue.call(this[_privateKey]._this, new SchemaArray(this, properties), properties);
                  }
              }
  
              try {
                  return getter.call(this, this[_privateKey]._obj[indexOrAliasIndex], properties);
              } catch (error) {
                  // This typically happens when the default value isn't valid -- log error.
                  this[_privateKey]._errors.push(error);
              }
          });
      }