robust-typing v1.0.0
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
Export | Description |
---|---|
type(x) | robust typing function |
is | object 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
istrue
thenx
is an instance ofKlass
. - if
x
is created with theKlass
constructor thenx
is a class instance ofKlass
. - Mere instances of
Klass
are instances but not class instances ofKlass
. - 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
test | description |
---|---|
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 objectx = Object.create(Foo.prototype)
or mere instances ofFoo
one degree away fromFoo.prototype
.userType(x)
incorrectly evaluates to"Foo"
rather than"Object"
.
- If
Foo
is an ES5 class, the programmer must make sure thatFoo.prototype.constructor
isFoo
.
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.
4 years ago