Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Restrict javascript class instances to particular properties

Tags:

javascript

I would like to define the structure of a class, and throw an error if the user attempts to set a property on one of my object instances using a property that is not defined in the class.

For example, say I have the following class:

class MyClass {
  constructor() {
    this.propertyA = 'A value';
    this.propertyB = 'Another value';
  }
}

And then when the user is modifying object instances...

let myInstance = new MyClass();
myInstance.propertyA = 'a new value'; // would work fine
myInstance.propertyC = 'unknown property value'; // throw exception

Is this possible? The seal keyword appears to be close to what I want. It would prevent new properties from being added, but I would like to throw exceptions in case the user type-o's the valid property names.

Update: Using Object.preventExtensions, Object.seal, or Object.freeze in strict mode will cause errors when a non-existent property is assigned to an object.

like image 753
benprime Avatar asked Jun 08 '26 23:06

benprime


1 Answers

You can use a Proxy to intercept new property additions and prevent new properties from being defined:

class MyClass {
  constructor() {
    this.propertyA = 'A value';
    this.propertyB = 'Another value';
    return new Proxy(this, {
      get: (_, prop) => this[prop],
      set: (_, prop, value) => {
        if (!(prop in this)) throw new Error('Prop does not exist!');
        this[prop] = value;
      }
    });
  }
}

let myInstance = new MyClass();
myInstance.propertyA = 'a new value'; // would work fine
console.log('about to set propertyC:');
myInstance.propertyC = 'unknown property value'; // throw exception

A much terser method that prevents new properties from being added is to use Object.preventExtensions(). Attempts to add new properties will throw an error in strict mode:

'use strict';
class MyClass {
  constructor() {
    this.propertyA = 'A value';
    this.propertyB = 'Another value';
    Object.preventExtensions(this);
  }
}

let myInstance = new MyClass();
myInstance.propertyA = 'a new value';
console.log('About to add propertyC');
myInstance.propertyC = 'unknown property value';
like image 91
CertainPerformance Avatar answered Jun 11 '26 13:06

CertainPerformance