Skip to content

Instantly share code, notes, and snippets.

@SethVandebrooke
Last active January 18, 2021 21:25
Show Gist options
  • Save SethVandebrooke/be9c202f6cb49804c413cc90bc2f3949 to your computer and use it in GitHub Desktop.
Save SethVandebrooke/be9c202f6cb49804c413cc90bc2f3949 to your computer and use it in GitHub Desktop.
Create models with enforced data types that can reference other models as data types themselves
function Model(name, OBJ) {
function model(obj) {
var PUBLIC = this;
var PRIVATE = {};
PUBLIC.MODEL_TYPE = name;
for (let key in obj) {
let value = obj[key];
// Ensure property is set correctly
if (key.match(/\w+_.+/) == null) {
throw new Error("Property does not contain both data type and property name: TYPE_NAME");
}
// Extract name and type from property
let type = key.substring(0, key.indexOf("_"));
let name = key.substring(key.indexOf("_") + 1, key.length);
// Map value to the private space
PRIVATE["__" + name] = value;
// Define the setter and getter
Object.defineProperty(PUBLIC, name, {
set: function (val) {
// Support null
if (val === null || val === undefined) {
PRIVATE["__" + name] = null;
}
// Enforce model types
if (val.MODEL_TYPE) {
if (val.MODEL_TYPE == type) {
PRIVATE["__" + name] = val;
} else {
throw new Error(name + " cannot be set as a " + (val.MODEL_TYPE) + " model because it is defined as a '" + type + "'");
}
} else { // Enforce data types
if (typeof val == type) {
PRIVATE["__" + name] = val;
} else {
throw new Error(name + " cannot be set to a " + (typeof val) + " because it is defined as a '" + type + "'");
}
}
},
get: function () {
return PRIVATE["__" + name];
}
});
}
return PUBLIC;
}
return function (obj) {
var m = new model(OBJ); // set default values
for (var k in obj) { // load specified values
if (m[k] !== undefined) {
m[k] = obj[k];
} else {
throw new Error(k + " is not specified as a property in the " + name + " model");
}
}
return m;
}
}
// property types are encforced
var test = new Model("t", {
string_MyName: "seth", // set a property type like so
number_num: 10
})
// models can be used as types
var test2 = new Model("t2", {
test_modelProperty: new test()
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment