© 2019 Meouzer Consortium

JavaScript: Quick Typing of Programmer Defined Classes

loading
Yeah! I'm the snarky cat named Meouzer
who does my best programming on browsers
but after taking the internet down
I gave a really big frown
and said that's what happens I'm smozered
Meouzer

See Symbol.toStringTag at MDN, which somehow just seems relevant since we actually use it.

Introduction

User class is short for programmer defined class. The userType() function will type user classes, however it is slower than the type() function, which does not type user classes (as of yet). For a user class Baz, Symbol.toStringTag comes to the rescue in which by defining Symbol.toStringTag as getter property of a class instance x in the constructor, we can make both nativeType(x) and type(x) evaluate to "Baz".

There are two potential problems to ponder.

  1. We already know that there is a problem in distinguishing between a class instance x of Baz, and y where y.__proto__ = Baz.prototype but y is not a class instance. An example of such a y is y = Object.create(Baz.prototype).
    • We want to make sure that nativeType(x), and type(x) are both "Baz", while nativeType(y) and type(y) are both "Object".
  2. Since the Symbol.toStringTag property of x is inherited, we need to make sure the nativeType and type of elements deriving from x like Object.create(x) are both "Object"

Quick Typing Example

The makeTypeable() function
function makeTypeable(className) { return `Object.defineProperty(this, Symbol.toStringTag, { get:function() { return (this.__proto__ === ${className}.prototype)? '${className}':'Object'; } });` } function Baz() { eval(makeTypeable('Baz')) } const x = new Baz(); console.log(nativeType(x)); // "Baz" console.log(nativeType(Baz.prototype)); // "Object" console.log(nativeType(Object.create(baz.prototype))); // "Object" console.log(nativeType(Object.create(x))); // "Object" console.log(type(x)); // "Baz" console.log(type(baz.prototype)); // "Object" console.log(type(Object.create(baz.prototype))); // "Object" console.log(type(Object.create(x))); // "Object"
Expanded
// Line 7 above expands to lines 14-16 below function baz() { Object.defineProperty(this, Symbol.toStringTag, { get:function() { return (this.__proto__ === baz.prototype)? "baz":" Object"; } }); }

So nativeType(x) === "Baz" is definitive test on whether an element x is a class instance of Baz. type(x) === "Baz" is another definitive test.