Last active
March 24, 2022 15:22
-
-
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
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 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