Search code examples
javascripttypesgoogle-closure-compilertypechecking

Check if an object is a Type in Google Closure, and convert it?


How can I check (at runtime) if an unknown object is a certain type? And then formally convert it to that type and do something with it?

I'd like to do something like this:

const /** {Object} */ someObject = {name: 'Apple', color: 'Red'};
if (someObject is Fruit) {
  // Convert to {Fruit} and do something with it.
  return /** {Fruit} */ (someObject);
}

where Fruit is a class with the attributes name and color.

To be more specific, I can't just create a Fruit object with a constructor as I'm getting the object from JSON.parse.

So far I've tried:

if (someObject instanceof Fruit)

this resolved to false. And I've tried:

const aFruit = /** @type {Fruit} */ someObj;

But this doesn't actually seem to do anything.. ie, when I pass in someObj that doesn't have properties name or color it is still treated as a Fruit.

Perhaps I need a more complex/custom solution? ie, is this built into Closure or should I just check the attributes on my own?


Solution

  • instanceof is what you are looking for. That's how you check if any given value was created from a specific constructor function (or better ES2015 class).

    const /** {Object} */ someObject = new Fruit('Apple', 'red'); 
    if (someObject instanceof Fruit) {
      // Convert to {Fruit} and do something with it.
      return /** {Fruit} */ (someObject);
    }
    

    However in your original example, what makes an object a Fruit? You are using anonymous objects. Is any object that has a name and color property a fruit? This is a bit unclear and very implementation specific. You need to be able to answer yourself "What makes an object a fruit?"

    If you want to check if an object implements a Fruit interface (has the correct properties), you simply check for those properties:

    /**
     * @param {!Object} obj
     * @return {boolean}
     */
    function isFruit(obj) {
      return obj.color && obj.name;
    }