BugHunterUK BugHunterUK - 6 months ago 12
Javascript Question

How can I ensure a function/method param is of a certian type?

Is it possible to ensure that a function/method paramater is of a certain type?

For example I have a simple Character class that accepts an optional

Health
object. Is it possible to check that the param is infact of type
Health
? I wouldn't want the consumer to pass in an integer when the application expects a
Health
object.

let Character = function(health) {
if(typeof health === 'undefined')
this.health = new Health(100);
else
this.health = health;
};

Character.prototype.hit = function(hitPoints) {
this.health.subtract(hitPoints);
};


Any ideas?

Answer

In this particular case, yes, you have two options:

  1. instanceof:

    if (health instanceof Health) {
        // It's a Health object *OR* a derivative of one
    }
    

    Technically, what instanceof checks is that the object Health.prototype refers to is in health's prototype chain.

  2. Check constructor

    if (health.constructor === Health) {
        // Its `constructor` is `Health`, which usually (but not necessarily)
        // means it was constructed via Health
    }
    

    Note that this is easy to fake: let a = {}; a.constructor = Health;

Normally you'd probably want to reach for the former, because A) It allows for subtypes of Health, and B) When doing inheritance hierarchies with ES5 and earlier syntax, a lot of people forget to fix constructor and it ends up pointing to the wrong function.

Example in ES5 syntax:

var Health = function() {
};

var PhysicalHealth = function() {
  Health.call(this);
};
PhysicalHealth.prototype = Object.create(Health.prototype);
PhysicalHealth.prototype.constructor = PhysicalHealth;

var h = new PhysicalHealth();
log(h instanceof Health);     // true
log(h.constructor == Health); // false

function log(msg) {
  var p = document.createElement('p');
  p.appendChild(document.createTextNode(msg));
  document.body.appendChild(p);
}

Or using ES2015 (ES6):

class Health {
}

class PhysicalHealth extends Health {
}

let h = new PhysicalHealth();
log(h instanceof Health);     // true
log(h.constructor == Health); // false

function log(msg) {
  let p = document.createElement('p');
  p.appendChild(document.createTextNode(msg));
  document.body.appendChild(p);
}

Comments