Skip to content

Instantly share code, notes, and snippets.

@o0101
Last active March 24, 2022 15:22
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 o0101/ab319ec827566dd9684b542198b6d8d9 to your computer and use it in GitHub Desktop.
Save o0101/ab319ec827566dd9684b542198b6d8d9 to your computer and use it in GitHub Desktop.
Very simple JavaScript type signatures and checking with pseudo-decorator syntax using tagged-template literals and computed property names
const Table = {};
let Id = 0;
class TypeClass {
constructor() {
const funcs = Object.getOwnPropertyNames(this.__proto__);
for( const funcName of funcs ) {
if (typeof this[funcName] === 'function' ) {
const typeSignature = Table[funcName];
if ( typeSignature && funcName.match(/func\d+/) ) {
//console.log({funcName,typeSignature});
const {name, paramTypes, returnType} = typeSignature;
const func = this[funcName];
this.__proto__[name] = (...args) => {
guardTypes(paramTypes, args);
const retVal = func.call(this, ...args);
guardType(returnType, retVal);
return retVal;
}
delete this.__proto__[funcName];
}
}
}
}
}
class Example extends TypeClass {
[T`concat${String},${String}->${String}`](s1,s2) {
return s1 + s2;
}
[T`add${Number},${Number}->${String}`](p,q) {
return (p+q)+'';
}
}
console.log(Example);
const xyz = new Example();
//console.log(xyz, Object.getOwnPropertyNames(xyz.__proto__));
console.log(xyz.concat('abc', 'xyz'));
console.log(xyz.add(131,45234));
console.log(xyz.add('11312',12321));
console.log(xyz.concat(12312,'dddd'));
function T(clips, ...slots) {
clips = Array.from(clips);
const [name] = clips;
const returnIndex = clips.findIndex(v => v.trim() === '->');
const paramTypes = slots.slice(0, returnIndex);
const [returnType] = slots.slice(returnIndex, returnIndex+1);
console.log({paramTypes, returnType});
const placeholder = ID();
Table[placeholder] = {
name, paramTypes, returnType
};
return placeholder;
}
function ID() {
return `func${Id++}`;
}
function guardTypes(types, vals) {
for( let i = 0; i < types.length; i++ ) {
const type = types[i];
const val = vals[i];
guardType(type, val);
}
}
function guardType(type, val) {
//console.log({type,val});
if (!(
val instanceof type ||
val?.constructor === type ||
typeof val === type ||
val?.__type__ === type ||
type?.hasInstance?.(val)
)) {
throw new TypeError(`Value ${val} was supposed to be Type ${type?.name || type}. It was not.`);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment