@lcf.vs/abstract
Version:
A simple base abstract class, in JavaScript, to extend with immutables & type forcing
54 lines (42 loc) • 1.41 kB
JavaScript
function error (message) {
throw new TypeError(message)
}
function has ([name, type]) {
const constructor = this.constructor
if (!this.hasOwnProperty(name)) {
error(`Missing required member ${name} of class "${constructor.name}"`)
}
if (!isPrototypeOf(type, this[name])) {
error(`Member ${name} of class "${constructor.name}" must be a ${type.name}`)
}
}
function all (requirements) {
Object.entries(requirements).forEach(has, this)
}
function isPrototypeOf (constructor, value = null) {
const type = typeof value
return value !== null
&& (
(type === 'object' && constructor.prototype.isPrototypeOf(value))
|| (value.constructor === constructor && (type !== 'number' || !Number.isNaN(value)))
)
}
function set ([name, value]) {
Object.defineProperty(this, name, {
enumerable: true,
value
})
}
export default class Abstract {
constructor (constructor = Abstract, immutables = {}, ...requirements) {
const name = this.constructor.name
if (this.constructor === constructor) {
error(`Abstract class "${name}" cannot be instantiated directly`)
}
if (!isPrototypeOf(constructor, this)) {
error(`Illegal invocation of abstract class "${name}"`)
}
Object.entries(immutables).forEach(set, this)
requirements.slice().reverse().forEach(all, this)
}
}