Gorgan Razvan
Gorgan Razvan

Reputation: 401

Instantiate JavaScript constructor function only if parameter types check

Let's say I have the following constructor function

function Planet(solarSystem,habitable) {

    this.solarSystem = solarSystem;
    this.habitable = habitable;

}

And I want to create an instance of this constructor function but I put the wrong parameters type (e.g. because I had 4 beers and I felt like programming):

let earth = new Planet(23, 'wooow');

Question: How can I condition the creation of the instance so that if parameter types are respected --> instance created, otherwise don't assign anything to earth

EDIT: I forgot to specify that I am expecting a Planet(String, boolean) parameters type

Upvotes: 0

Views: 673

Answers (2)

Egor Stambakio
Egor Stambakio

Reputation: 18146

You can use a Proxy object to intercept an existing constructor and apply your validation logic:

function Planet(solarSystem,habitable) {
    this.solarSystem = solarSystem;
    this.habitable = habitable;
}

const validate = { // handler for Proxy
  construct: function(target, args) {
    let solarSystem, habitable;
    if (Array.isArray(args) && args.length === 2) {
      solarSystem = (typeof args[0] === 'string') ? args[0] : null;
      habitable = (typeof args[1] === 'boolean') ? args[1] : null;
      return ( solarSystem !== null && habitable !== null)
      	? { solarSystem, habitable} 
        : {}
    } else {
    	return {} // return an empty object in case of bad arguments
    }
  }
}

// new constructor, use it to create new planets
const validPlanet = new Proxy(Planet, validate); 
// usage: const a = new validPlanet(<string>, <boolean>)

// let's use initial buggy constructor:

const earth = new Planet('solar', true);
console.log('earth (Planet): ', earth);

const wrong = new Planet('solar', 15); // this uses the initial constructor, wrong value passes
console.log('wrong (Planet): ', wrong);

// now let's use proxied constrictor with validation

const pluto = new validPlanet('solar', false);
console.log('pluto (validPlanet): ', pluto);

const bad = new validPlanet('solar', 'hello');
console.log('bad (validPlanet): ', bad); // returns an empty object

It's impossible to return 'undefined' here if you provide wrong inputs, because Proxy.construct must return an object. If an empty object is ok, then this should work for you.

Upvotes: 0

taile
taile

Reputation: 2776

There are some solutions to do it:

  • return an object without any property

    function Planet(solarSystem,habitable) {
        if (typeof solarSystem != 'string' && typeof habitable != 'boolean') {
           return Object.create(null);
        }
        this.solarSystem = solarSystem;
        this.habitable = habitable;
    }
    
    var planetObj1 = new Planet('TEST', true);
    console.log('planetObj1 ' , planetObj1 , 'is instanceof Planet', planetObj1 instanceof Planet);
    var planetObj2 = new Planet(14, 'TEST');
    console.log('planetObj2 ', planetObj2, 'is instanceof Planet', planetObj2  instanceof Planet);

  • if you want to return any others JavaScript type such as undefined, null. You can create a prototype to handle it

You can create a prototype to decide to create your new Obj or not

function Planet(solarSystem,habitable) {

        this.solarSystem = solarSystem;
        this.habitable = habitable;

    }

    Planet.CreatePlanet = function(solarSystem, habitable) { 
        if (typeof solarSystem != 'string' && typeof habitable != 'boolean') return null;
        return new Planet(solarSystem, habitable);
    }

    // then instead of new Planet():
    var obj = Planet.CreatePlanet(14, 'habitable');//return null
    console.log(obj);

Upvotes: 1

Related Questions