Skip to content

Instantly share code, notes, and snippets.

@sag1v
Last active July 4, 2019 13:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sag1v/50901c8285a12e904b609c833ce2db51 to your computer and use it in GitHub Desktop.
Save sag1v/50901c8285a12e904b609c833ce2db51 to your computer and use it in GitHub Desktop.
A run-time type checker with proxies
function typeCheck(obj, definition) {
return new Proxy(obj, {
set(obj, key, value) {
if (key in definition && typeof value !== definition[key]) {
throw new TypeError(`Invalid type of ${key} '${typeof value}'. expected to be '${definition[key]}'`)
}
return Reflect.set(obj, key, value);
}
});
}
const userShape = {
name: 'string',
age: 'number'
}
class TypeSafe{
constructor(shape){
return typeCheck(this, shape);
}
}
class User extends TypeSafe{
constructor(name, age){
super(userShape);
this.name = name;
this.age = age;
}
}
let myUser = new User('sagiv', '36'); // throws -> TypeError: Invalid type of age 'string'. expected to be 'number'
// support nested objects
function typeCheck(obj, definition) {
const validator = {
set(obj, key, value) {
if (key in definition) {
if (Object.prototype.toString.call(value) === "[object Object]") {
// this is an object
Object.entries(value).forEach(([oKey, oVal]) => {
// proxy the set of each key
const nested = typeCheck(value, definition[key]);
Reflect.set(nested, oKey, oVal);
});
} else if (typeof value !== definition[key]) {
throw new TypeError(`Invalid type of ${key} '${typeof value}'. expected to be '${definition[key]}'`)
}
}
return Reflect.set(obj, key, value);
}
}
return new Proxy(obj, validator);
}
const userShape = {
name: 'string',
age: 'number',
address: {
where: 'string'
}
}
class TypeSafe {
constructor(shape) {
return typeCheck(this, shape);
}
}
class User extends TypeSafe {
constructor(name, age, address) {
super(userShape);
this.name = name;
this.age = age;
this.address = address;
}
}
let myUser = new User('sagiv', 36, {
where: 0
}); // throws -> TypeError: Invalid type of where 'number'. expected to be 'string'
@sag1v
Copy link
Author

sag1v commented Mar 14, 2019

TODO: add complex objects support

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment