<div dir="ltr"><div><div><br>> Part of this has had me considering if freezing classes (and all 
recursively referenced types) used in the type system is viable.<br><br></div>function foo(bar: Array.<Set>) {<br></div>//whatever<br><div>}<br><br></div><div>[Array, Set] = [Set, Array];<br></div><div>foo(new Array([Set()]));<br></div><div><br></div><div>You can't freeze all builtins for obvious reasons.<br><br><br></div><div>You totally omitted point that your type system can't use or describe this function:<br><br><span style="font-family:monospace,monospace"><br></span></div><div><span style="font-family:monospace,monospace">function issue(Ctor) {<br></span></div><div><span style="font-family:monospace,monospace">   assert(Reflect.isConstructor(Ctor)); // Type system don't provide way to disguintish object with [[Construct]] and [[Call]] methods.<br></span></div><div><span style="font-family:monospace,monospace">   assert(Foo.isPrototypeOf(Ctor)); // Type system don't provide way to ensure prototypal inheritance<br></span></div><div><span style="font-family:monospace,monospace">   const retClass = class extends Ctor { // Type system don't provide way to describe types being returned from function<br></span></div><div><span style="font-family:monospace,monospace">   };<br></span></div><div><span style="font-family:monospace,monospace">   Object.assign(retClass.prototype, mixin); // Object.assign can be overridden to do anything, so actual code execution is required to prove it's valid<br></span></div><div><span style="font-family:monospace,monospace">   return retClass;<br></span></div><div><span style="font-family:monospace,monospace">}</span><br></div><div><br><br></div><div>TypeScript favors OOP because it supports virtually all OOP idioms, but doesn't support non-basic FPP idioms.<br></div><div><br></div></div>