type PseudoKeys = ["hover"|"before"|"after"] | ["hover", "after"|"before"]; type ValueSignature = (...args:number[])=>void type EnumDefinition = [property:string, options:Record, values?:Signature]; type EnumBlock = Record>; type RecursiveObject> = { [F in keyof Obj]: Obj[F][2] extends Sig ? ((...args:Parameters)=> RecursiveObject&((...args:PseudoKeys)=>RecursiveObject)&Array>)&{ [E in keyof Obj[F][1]]:RecursiveObject&((...args:PseudoKeys)=>RecursiveObject)&Array> } : { [E in keyof Obj[F][1]]:RecursiveObject&((...args:PseudoKeys)=>RecursiveObject)&Array> } } function Block>(options:Fields):()=>RecursiveObject { return ()=>{ let pseudo = false; let query = false; const list = []; let fieldLookup = {}; const proxyOuter = new Proxy( function(...args) { console.log("outer: core call", ...args) if(args.length) { list.push(`${(pseudo||query) ? "}" : ""} &:${args.join("::")}{`); pseudo = true; query = false; return proxyOuter; } pseudo && list.push("}"); query && list.push("}"); pseudo = false; query = false; return list; }, { get(_target, propName) { console.log("outer: reading property", propName); const sizeCheck = parseInt(propName) if(sizeCheck) { list.push(`${(query) ? "}" : ""} @media(min-width:${sizeCheck}px){`); query = true; return proxyOuter; } fieldLookup = options[propName]; if(fieldLookup) { list.push(fieldLookup[0]); } return proxyInner; } } ); const proxyInner = new Proxy( function(...args) { console.log("inner: core call", ...args) list.push(`:${args.join(" ")};`); return proxyOuter; }, { get(_target, valName) { console.log("inner: reading property", valName); try { list.push(`:${fieldLookup[1][valName]};`); return proxyOuter; } catch(e) { console.warn("someone is trying to stringify a style proxy"); return ()=>"[StyleProxy]"; } } } ); return proxyOuter; } } const styles = Block( { Pos:["position", { Abs:"absolute", Rel:"relative" }], Display:[ "display", { Flex:"flex", Grid:"grid", None:"none", Block:"block", InlineBlock:"inline-block" }], Left:[ "left", { Auto:"auto" }, (left)=>{}] } ); const userDeclaredStyleBlock = (styles() .Pos.Abs ("hover", "after") .Pos.Rel .Left(20) [512] .Left(100)) // internal stringification console.log(userDeclaredStyleBlock().join("")); function Sheet>>(userClasses:UserClasses):{[Class in keyof UserClasses]:string} { return new Proxy({}, {get(_target, className){}}); }