George 2.0 Hope
George 2.0 Hope

Reputation: 648

{Symbol.toStringTag} not working for Error object

For a starting reference point, I read the following:

• Customizing ES6 via well-known symbols

http://2ality.com/2015/09/well-known-symbols-es6.html

... and based on the examples/code above & the section:

○ Default toString tags

http://2ality.com/2015/09/well-known-symbols-es6.html#default-tostring-tags

... I would expect that one or both the following approaches would allow me override the behavior of the "Error Object" when it's used in "console.log(returnVal)" for instance:

console.log("Approach #1");
class CoolError extends Error {
  constructor (args) {
    super(args);
  }
  [Symbol.toPrimitive] (hint) {
    return "*************" + this.name + " : " + this.message;
    // note: I shouldn't need this, however, it doesn't work either...
  }
  [Symbol.toStringTag] (hint) {
    return ">>>>>>>>>>>>>" + this.name + " : " + this.message;
  }
}
returnVal = new CoolError("errMsg");
console.log("returnVal[Symbol.toPrimitive] === " + returnVal[Symbol.toPrimitive]);
console.log(" ");
console.log(returnVal);

console.log(">");
console.log(" >");
console.log("  >");
console.log("   >");

console.log("Approach #2");
returnVal = new Error("errMsg");
console.log("returnVal[Symbol.toStringTag] === " + returnVal[Symbol.toStringTag]);
returnVal[Symbol.toStringTag] = function (hint) {return "*************" + this.name + " : " + this.message};
console.log("returnVal[Symbol.toStringTag] === " + returnVal[Symbol.toStringTag]);
console.log(" ");
console.log(returnVal);

... ... however, no such luck... in both cases, the console.log(returnVal) statements return the entire Error stack trace (which is what I'm trying to prevent).

I would like to point out that I can successfully "set" the behaviors of a custom object:

So I know the general approach 'works', I just can't seem to make it work with regards to the built in Error object.

class AnswerToLifeAndUniverseAndEverything {

    [Symbol.toPrimitive] (hint) {
        console.log(typeof hint);
        console.log(hint);
        if (hint === 'string') {
            console.log('string');
            return 'Like, 42, man';
        } else if (hint === 'number') {
            console.log('number');
            return 42;
        } else {
            console.log('default');
            // when pushed, most classes (except Date) default to returning a number primitive
            return 42;
        }
    }
}

var answer = new AnswerToLifeAndUniverseAndEverything();

console.log(  Number(answer) + " === 42");
console.log(  String(answer) + " === 'Like, 42, man'");

(Also, I'd like for it to work using both attempt approaches #1 & #2 above, if possible.)

Any ideas?

Upvotes: 0

Views: 822

Answers (1)

loganfsmyth
loganfsmyth

Reputation: 161467

You are misunderstanding a few main things.

I would expect that one or both the following approaches would allow me override the behavior of the "Error Object" when it's used in "console.log(returnVal)" for instance:

console.log has no official spec for how it will display an object. To my knowledge, none of the current implementations use toString. Node specifically allows objects to have a .inspect function to return a value to render, but that's about it.

Second, you appear to be misunderstanding what toStringTag is for. toStringTag is specifically a tag string value. It is not a function, which is why your function isn't doing anything. A toStringTag usage might look like

var obj = {};
obj.toString(); // [object Object]
obj[Symbol.toStringTag] = "MyCustomThing";
obj.toString(); // [object MyCustomThing]

and that's it. It's a simple string value for use with the default implementation of .toString() on an object.

Given what you're looking for, your solution would be overriding Symbol.toPrimitive, or more easily probably just overriding .toString since that will have exactly the same behavior in this case. Then when you log your object, just convert it to a string first, just like you're doing in AnswerToLifeAndUniverseAndEverything.

class CoolError extends Error {
  constructor (args) {
    super(args);
  }
  toString() {
    return "*************" + this.name + " : " + this.message;
  }
}
var returnVal = new CoolError("errMsg");

console.log("" + returnVal)
// *************Error : errMsg

Upvotes: 1

Related Questions