Created
July 6, 2015 07:49
-
-
Save Gwash3189/5541568214f5c4c22cb8 to your computer and use it in GitHub Desktop.
runtime type checking idea with decorators
This file contains 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
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