@simbolco/class-utils v1.0.1
Class Utilities Library
An ECMAScript 5+ library which provides utilities for classes or class-like functions. TypeScript support is provided out of the box.
This library is web, CommonJS, and RequireJS compatible. In web browsers, the
global variable classUtils contains this library's exports.
The code which this library consists of is licensed under the Mozilla Public License version 2.0. This means that this code can be reused and integrated into other projects so long as the following conditions are satisfied:
- The source code pertaining to this library must be publically accessible and available when distributed.
- A copy of the license and copyright notice must be included with the library.
- Any modifications to this library must be released under the Mozilla Public License version 2.0 or a sufficiently similar license when distributing it.
Basic Usage
restrict
The restrict function restricts all configurable instance getters, setters,
and methods of a given class to only being able to be called by instances said
class. restrict additionally sets all non-configurable static and method
properties of a class to be non-configurable and non-enumerable. Data properties
are further set as non-writable and, finally, the class is given a
Symbol.toStringTag which matches the name property of the constructor.
import { restrict } from '@simbolco/class-utils';
class A_Class {
get x() {
// ...
}
y() {
// ...
}
// if static blocks are supported:
static {
restrict(this);
}
}
// if static blocks aren't supported:
restrict(A_Class);
A_Class.prototype.x; // throws a TypeError
A_Class.prototype.y.call(new Date); // throws a TypeError
A_Class.prototype.x = function() {
// ...
}; // failssealed
The sealed function prevents further extension of the static or instance
properties and methods of a class using Object.seal.
import { sealed } from '@simbolco/class-utils';
class SomeClass {
// ...
// if static blocks are supported:
static {
sealed(this);
}
}
SomeClass.new_property = 1; // failsisConstructor
The isConstructor function duck types whether a given function is a
constructor.
import { isConstructor } from '@simbolco/class-utils';
class AnotherClass {
// ...
}
isConstructor(AnotherClass); //> true
isConstructor(String); //> true
isConstructor("a string"); //> false
isConstructor(Array.prototype.indexOf); //> false
isConstructor(() => "arrow function"); //> false
isConstructor(function() { //> true !!
return "classic function";
});propertiesOf
The propertiesOf function returns an iterator over a given object's own keys
and property descriptors. The keys includes both strings and symbols.
This is provided as an ease of implementing your own class decorators or utility functions.
import { propertiesOf } from '@simbolco/class-utils';
for (const [key, descriptor] of propertiesOf(AnotherClass.prototype)) {
// process the descriptor...
}Advanced Usage
Decorators
In TypeScript with the experimental decorators extension enabled or JavaScript
implementations which support the TC-39 class decorators proposal, the restrict and sealed
functions can be used as decorators:
@sealed @restrict class LockedDown {
// ...
}Excluding properties from being restricted
The restrict function takes an optional options parameter in both its
functional and decorator forms. With it, one can specify static and instance
property keys which the implementor would prefer to not have restricted or
otherwise set as non-configurable, non-enumerable, and non-writable.
const FunctionalOptions = restrict(class {
// ...
}, {
exclude: ['propD', 'propE'],
excludeStatic: [Symbol.toStringTag]
});
@restrict({
exclude: ['propA', 'propB'],
excludeStatic: ['propC']
}) class DecoratorOptions {
static propC = 1;
static propD = 2;
// ...
}
DecoratorOptions.propC = 3; // succeeds
DecoratorOptions.propD = 4; // fails
DecoratorOptions.propC; //> 3
DecoratorOptions.propD; //> 2Classes which have already been passed into restrict cannot be restricted
again, thus static or instance excludes can only be provided once.
Custom @@toStringTag name
A custom Symbol.toStringTag string can be passed as an option to restrict
via the name property of the options parameter:
@restrict({ name: "Y" }) class X {}
Object.prototype.toString.call(new X) //> "[object Y]"Programming Interface
isConstructor
Parameters
- obj - An object.
Returns
True if obj duck types to a constructor (i.e. its typeof is "function" and
has its own prototype property). False otherwise.
propertiesOf
Parameters
- obj - An object.
Returns
An iterator of a obj's own property keys and descriptors as a read-only array.
restrict
A decorator which performs the following actions on all configurable properties of a given constructor and its prototype that are not explicitly marked in the options parameter as excluded:
- Sets the property to be non-configurable.
- Sets the property to be non-enumerable.
- If the property is a data property, it is set to be non-writable.
In addition to the above steps, the following actions are performed on all
configurable properties of a given constructor's prototype, except for the
constructor property:
- If the property is a getter/setter property, the get and set functions are restricted to only allowing calls from class instances.
- If the property is a data property corresponding to a function, the property is restricted to only allowing calls from class instances.
If the provided constructor does not already have its own a Symbol.toStringTag
property defined, this function will provide one corresponding to either the
name field of the options parameter or the name property of the provided
constructor.
Parameters
- iface - A constructor to restrict the methods, getters, and setters of.
- options - (optional) Property keys to not apply restrictions to and/or the name tag to provide to iface.
Returns
The iface parameter.
sealed
A decorator which seals a provided constructor and its prototype, preventing extension, modification, or tampering of their properties.
Parameters
- iface - A constructor to seal.
Returns
The iface parameter.