Ways to type check in javascript

Asked

Viewed 53 times

0

I am studying Javascript, and I came across a question, which I present below, I found several ways to solve the same case in Javascript, and I show you what I chose. I wonder if you know other ways, and how to better deal with this kind of situation, letting the compiler work as I did would be a really good way to deal with the issue or am I mistaken?

// Utilizando a sintaxe de módulos, AssetPackage está
// em um arquivo diferente de PackageManager

function AssetPackage(name, assets) {
    this.name = name;
    this.assets = assets;
}

function PackageManager() {
    this.packages = {};
}

I can’t let objects that aren’t packages be added a Packages, as this could make the API work badly. I imagined the following ways to solve this:

Way 1 - instanceof

// Importo AssetPackage
PackageManager.prototype.addPackage = function(assetPackage) {
    if (!this.isAssetPackage(assetPackage))
      return false;

    this.packages[assetPackage.name] = assetPackage;
}

PackageManager.prototype.addPackages = function(assetPackages) {
    if (!this.isAssetPackage(assetPackage))
      return false;

    for(let i = 0; i < assetPackages.length; i++)
        this.packages[assetPackages[i].name] = assetPackages[i];
}

PackageManager.prototype.isAssetPackage = function(val) {
    return (val instanceof AssetPackage);
}

Way 2 - Checking properties

// Não importo AssetPackage
PackageManager.prototype.addPackage = function(assetPackage) {
    if (!assetPackage.name || !assetPackage.assets)
        return false;

    this.packages[assetPackage.name] = assetPackage;
}

PackageManager.prototype.addPackages = function(assetPackages) {
    for(let i = 0; i < assetPackages.length; i++)
        if (!assetPackages.name || !assetPackages.assets)
            continue;
            this.packages[assetPackages[i].name] = assetPackages[i];
}

Way 3 - Checking properties and assigning them only

// Não importo AssetPackage
PackageManager.prototype.addPackage = function(assetPackage) {
    if (!assetPackage.name || !assetPackage.assets)
        return false;

    this.packages[assetPackage.name] = {
        name: assetPackage.name,
        assets: assetPackage.assets
    };
}

PackageManager.prototype.addPackages = function(assetPackages) {
    for(let i = 0; i < assetPackages.length; i++)
        if(!assetPackages.name || !assetPackages.assets)
            continue;
        this.packages[assetPackages[i].name] = {
            name: assetPackages[i].name,
            assets: assetPackages[i].assets
    };
}

Way 4 - Checking properties and whether an object is passed

// Não importo AssetPackage
PackageManager.prototype.addPackage = function(assetPackage) {
    if (!this.isObject(assetPackage) || !assetPackage.name || !assetPackage.assets)
        return false;

    this.packages[assetPackage.name] = {
        name: assetPackage.name,
        assets: assetPackage.assets
    };
}

PackageManager.prototype.addPackages = function(assetPackages) {
    if (!Array.isArray(assetPackages))
        return false;

    for(let i = 0; i < assetPackages.length; i++)
        if(!this.isObject(assetPackages) || !assetPackages[i].name || !assetPackages[i].assets)
            continue;
        this.packages[assetPackages[i].name] = {
            name: assetPackages[i].name,
            assets: assetPackages[i].assets
    };
}

PackageManager.prototype.isObject = function(val) {
    return (typeof val === "object" && val !== null);
}

Way 5 - constructor.name

PackageManager.prototype.addPackage = function(assetPackage) {
    if (!isAssetPackage(assetPackage))
      return false;

    this.packages[assetPackage.name] = assetPackage;
}

PackageManager.prototype.addPackages = function(assetPackages) {
    if (!isAssetPackage(assetPackage))
      return false;

    for(let i = 0; i < assetPackages.length; i++)
        this.packages[assetPackages[i].name] = assetPackages[i];
}

PackageManager.prototype.isAssetPackage = function(val) {
    return (getType(val) === 'AssetPackage');
}

PackageManager.prototype.getType = function (o) { 
    return o && o.constructor && o.constructor.name; 
}

Way 6 - The chosen one. Do not check any! let the compiler work.

// Importo AssetPackage
PackageManager.prototype.addPackage = function(assetPackage) {
    this.packages[assetPackage.name] = assetPackage.assets;
}

PackageManager.prototype.addPackages = function(assetPackages) {
    for(let i = 0; i < assetPackages.length; i++)
        this.packages[assetPackages[i].name] = assetPackages[i].assets;
}

// ou
PackageManager.prototype.addPackage = function(assetPackage) {
    this.packages[assetPackage.name] = {
      name: assetPackage.name,
      assets: assetPackage.assets
    };
}

PackageManager.prototype.addPackages = function(assetPackages) {
    for(let i = 0; i < assetPackages.length; i++)
        this.packages[assetPackages[i].name] = {
          name: assetPackages[i].name,
          assets: assetPackages[i].assets
        };
}

I chose to let the compiler work for the following reasons, if I return a "false" or whatever it is to return to the API user, it could simply ignore the false by inattention, this would cause errors in your code if it does not correctly check the return of the API functions, already letting the compiler work, your code would simply not compile and it would be warns with an error, probably of "Undefined" property or something like that, and a build error he can’t ignore. That would avoid mistakes by carelessness.

  • Have you ever thought of using throwand specify errors? At the moment your code tries to access this property the compiler will release a throw undefined property(Undefined), with a simple debug the programmer could find(or not kkk), customizing and specifying with a try...catch can facilitate the life of the subject.

  • @Mslacerda In fact I think I was mistaken, the way 6 would serve to null and Undefined, but perhaps it would be better to use "instanceof", because what if I pass an empty object or empty array? or even an object without the properties it needs to have, it will create a "Undefined" property in Packages, and I don’t want that. But you could use a throw too, create an answer with your way.

  • Um, there might actually be this problem, but anyway this mistake would pop up somewhere ahead, I particularly don’t like the idea of returning false (I find it a bad practice in this case), but let’s wait if someone has a better answer...

  • @Mslacerda thought of one more, a duck mixed with console.error kkkkkkk if (!this.isObject(assetPackage) || !assetPackage.name || !assetPackage.assets)&#xA; return console.error('You must pass an AssetPackage as an argument to addPackage.'); kkkkk Of course q n should do this kkkk But maybe just returning a false will be better.

  • @Mslacerda A better solution then is to use throw as you said, but we don’t need Try/catch here: if (!this.isObject(assetPackage) || !assetPackage.name || !assetPackage.assets)&#xA; throw new TypeError('You must pass an AssetPackage as an argument to addPackage.');

  • I think you’re getting lost trying to use a non-typed language as if it were typed.

  • @bfavaretto feel this, but what is the other way to deal with the same case more suitable to Javascript? would simply not do any checking?

Show 2 more comments
No answers

Browser other questions tagged

You are not signed in. Login or sign up in order to post.