1.0.0 • Published 4 years ago

robust-typing v1.0.0

Weekly downloads
-
License
ISC
Repository
-
Last release
4 years ago

Introduction to robust-typing

Obviously JavaScript should have an extensive robust data-typing system but doesn't. So one is supplied with the type() function. Only robust typing allows for deep copying and serialization/deserialization of complex JavaScript objects, including class instances of ES5 and ES6 programmer defined classes.

P.S. You can easily type your own classes. See makeTypable() below in the Exported Functions Detail section. E.g.,

    const x = new MyClass(); 
    type(x) is "MyClass"

##Installation and Usage

npm install robust-typing
const {type, is, makeTypeable, ...} = require('robust-typing')

Exports

ExportDescription
type(x)robust typing function
isobject whose function properties test for the various data types
makeTypeable(className)allows type() function to type class instances of programmer defined classes
nativeType(x)what JavaScript supplies but is so random that it is nearly useless
dtype(x)not of real interest, but supplies headers to the author's stringify/serialization function
userType(x)also types programmer defined classes. slightly deprecated, so only use in a pinch. use makeTypeable() instead if practical

Supports

Code works in Node.js, Edge, Firefox, Chrome, and Opera. IE11 is not supported since a symbol is used and IE11 does not support symbols.

Role in Library

The author plans to publish to npm robust serialization/deserialization, and deep copy modules that rely on the robust-typing package. You can serialize/deserialize and deep copy programmer defined ES5 and ES6 classes.

Nomenclature

  • If x instanceof Klass is true then x is an instance of Klass.
  • if x is created with the Klass constructor then x is a class instance of Klass.
  • Mere instances of Klass are instances but not class instances of Klass.
  • The secondary objects of Klass are
    • Klass.prototype
    • Mere instances of Klass.

In typing, care must be taken to distinguish between class instances of Klass and secondary Klass objects. The former should type to "Klass", while the latter should type to "Object".

Specification of type()

type(x)x
"null"a null primitive
"undefined"an undefined primitive
"boolean"a boolean primitive
"number"a number primitive
"string"a string primitive
"bigint"a bigint primitive
"symbol"a symbol primitive
"Boolean"a class instance of Boolean
"Number"a class instance of Number
"String"a class instance of String
"Date"a class instance of Date
"RegExp"a class instance of RegExp
"Error"a class instance of Error
"EvalError"a class instance of EvalError
"RangeError"a class instance of RangeError
"ReferenceError"a class instance of ReferenceError
"SyntaxError"a class instance of SyntaxError
"TypeError"a class instance of TypeError
"URIError"a class instance of URIError
"Array"a class instance of Array
"Arguments"a function's argument list
"Function"a function
"Int8Array"a class instance of Int8Array
"Uint8Array"a class instance of Uint8Array
"Uint8ClampedArray"a class instance of Uint8ClampedArray
"Int16Array"a class instance of Int16Array
"Int32Array"a class instance of Int32Array
"Uint32Array"a class instance of Uint32Array
"Float32Array"a class instance of Float32Array
"Float64Array"a class instance of Float64Array
"ArrayBuffer"a class instance of ArrayBuffer
"DataView"a class instance of DataView
"Map"a class instance of Map
"Set"a class instance of Set
"WeakMap"a class instance of WeakMap
"WeakSet"a class instance of WeakSet
"Buffer"a class instance of Buffer
"global"the Node.js global object
"Window"a Browser window object
"HTMLDocument"a Browser document object
"HTMLDivElement"a Browser Div DOM element.Same for any other Dom element.
"Object"an object not classified above

Properties of the is Object

testdescription
is.Object(x)is x an object?
is.Primitive(x)is x a primitive?
is.ErrorVariant(x)is x a class instance of Error or other variant Error class?
is.Arguments(x)is x an arguments list?
is.HostObject(x)is x a window, document, or DOM object?
is.NodeEnvironment()is running in Node.js as opposed to Browser?
is.BrowserEnvironment()is running in Browser as opposed to Node.js?
is.Klass(x)is x a Klass class instance? (where Klass is a built-in data type class.)

Exported Functions Detail

makeTypable(className)

Let Foo be a programmer defined class. Class instances of Foo are correctly typed by type() if eval(makeTypeable('Foo')) is written in the constructor.

    Foo()
    {
        eval(makeTypable('Foo'));
    }
    
    const x = new Foo(); // class instance of Foo
    console.log(type(x) === 'Foo'); // true 
    
    // make sure secondary objects of Foo are typed to 'Object'
    
    console.log(type(Foo.prototype) === 'Object') // true
    console.log(type(Object.create(Foo.prototype)) === 'Object') // true
    console.log(type(Object.create(x)) === 'Object') // true

nativeType(x)

    function nativeType(x)
    {
       const str = Object.prototype.toString.call(x);
       return str.substring(8, str.length-1); 
    }

The nativeType(x) function is familiar to many if not by this name. It should provide full robust typing out of the box, but it doesn't. It doesn't always type correctly, especially for secondary objects.

    console.log(nativeType(Set.prototype)); // logs "Set" not "Object"
    console.log(nativeType(Object.create(Set.prototype))); // logs "Set" not "Object"
    console.log(nativeType(Object.create(new Set()))); // logs "Set" not "Object"    

nativeType() is the only hook to robust typing, but is so random that extensive nuanced work is required to turn nativeType() into the robust type() function. Every built in class has its own idiosyncrasies that enable type() to work correctly. Sometimes the native type is inherited, and sometimes it isn't, amongst other peculiarities.

userType(x)

Let Foo be a programmer defined class. If makeTypable() is not used then type() will not correctly type class instances of Foo. However, userType() will. There are two caveats.

  • userType() will incorrectly type the secondary object x = Object.create(Foo.prototype) or mere instances of Foo one degree away from Foo.prototype. userType(x) incorrectly evaluates to "Foo" rather than "Object".
  • If Foo is an ES5 class, the programmer must make sure that Foo.prototype.constructor is Foo.

dtype(x)

The reader can forget about this function. It is exported for use in the author's serialization/stringification function to be published to npm at a later date.

Testing (is extensive)

cd node_modules/robust-typing npm test run test.js in the IDE

All tests passed. Well, except for three expected errors for the userType() function. This is why it was previously mentioned that userType() is somewhat deprecated. If Foo is a programmer defined class then userType() incorrectly types the secondary object Object.create(Foo.prototype) as "Foo". If that's OK then userType() is OK. However, use of makeTypable() is more efficient and works 100% with the type() function.