Last active
January 18, 2021 21:25
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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