Skip to content

Instantly share code, notes, and snippets.

@Gwash3189
Created July 6, 2015 07:49
Show Gist options
  • Save Gwash3189/5541568214f5c4c22cb8 to your computer and use it in GitHub Desktop.
Save Gwash3189/5541568214f5c4c22cb8 to your computer and use it in GitHub Desktop.
runtime type checking idea with decorators
const _string = (v) => typeof v === "string"
const _none = (v) => v === undefined || v === null;
function string(target, name, desc) {
return createNewDescriptor("string", _string).apply(null, arguments);
}
function none(target, name, desc) {
return createNewDescriptor("undefined", _none).apply(null, arguments);
}
function func(...checkers) {
return function(target, name, desc) {
return {
value: function(...args) {
let result = args.filter((x, i) => {
return checkers[i](x);
}).length;
result = result === checkers.length || (result + 1) === checkers.length;
if (result) {
if(checkers.length === (result + 1)){
let ret = desc.value.apply(target, args);
if(checkers[checkers.length-1](ret)){
return ret;
} else {
throw new TypeError(`Incorrect return type of ${typeof ret}`);
}
} else {
return desc.value.apply(target, args);
}
if (desc.value) {
if(checkers.length === (result + 1)){
let ret = desc.value.apply(target, args);
if(checkers[checkers.length-1](ret)){
return ret;
} else {
throw new TypeError(`Incorrect return type of ${typeof ret}`);
}
} else {
return desc.value.apply(target, args);
}
} else {
return desc.initializer().apply(target, args);
}
}
},
enumerable: true
}
}
}
function createNewDescriptor(typeName, checkerFunc, val = undefined) {
return function(target, name, desc) {
if (arguments.length === 1) {
if(checkerFunc(target)){
return true;
} else {
throw new TypeError(`Was given a ${typeof target} but was expecting ${typeName}`);
}
} else {
let value = null;
let descriptor = {
get() {
return value;
},
set(v) {
if (checkerFunc(v)) {
value = v;
} else {
throw new TypeError(`${name} was given a ${typeof v}, but requires a ${typeName}`);
}
},
enumerable: true,
}
if (val) {
descriptor.value = val;
}
return descriptor;
}
}
}
class C {
@string name;
@func(string, none) setName(name) {
this.name = name;
return true;
}
constructor(name) {
this.name = name;
}
}
c = new C("");
c.setName("asd");
c.setName(1);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment