title: Building a re-serializable wrapper class in TypeScript
body: <p>I'm working on a utility library for use with a complex API model. We receive JSON-parsed objects from the wire with some kind of guarantee about their structure, as follows:</p>
  <pre class="lang-js prettyprint-override"><code>// Known structure of the message:
  interface InputBox {
    top: number;
    height: number;
    left: number;
    width: number;
  }
  interface InputObj {
    box: InputBox
  }
  
  // User code (outside our scope) does something like:
  const inputObj: InputObj = JSON.parse(
    '{ &quot;box&quot;: { &quot;top&quot;: 0, &quot;height&quot;: 10, &quot;left&quot;: 1, &quot;width&quot;: 2, &quot;color&quot;: &quot;red&quot; } }'
  );
  </code></pre>
  <p>My goal is to create some view of the object which:</p>
  <ul>
  <li>Adds some utility functions &amp; properties</li>
  <li>Stringifies to the same/compatible JSON as the input</li>
  <li>Behaves consistently when treated as mutable</li>
  <li>Preserves any unexpected attributes, if possible</li>
  </ul>
  <p>For example, user code might look like:</p>
  <pre class="lang-js prettyprint-override"><code>// In-place or new obj constructor would both be fine:
  const easyObj = myCoolLibrary(inputObj);
  
  easyObj.box.top = 5;
  console.log(easyObj.box.getBottom());  // '15'
  
  JSON.stringify(easyObj);
  // -&gt; { &quot;box&quot;: { &quot;top&quot;: 5, &quot;height&quot;: 10, &quot;left&quot;: 1, &quot;width&quot;: 2, &quot;color&quot;: &quot;red&quot; } }
  // (Note box.color still present, although missing from the input interface)
  </code></pre>
  <p>After reading a little around options, it seems like:</p>
  <ul>
  <li>There could be a nice in-place solution using <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf" rel="nofollow noreferrer">Object.setPrototypeOf</a> to directly overwrite prototypes in the input, but it's quite recent and not sure if polyfilling for older browsers would work.</li>
  <li>Creating new objects (with classes/prototypes) and cloning properties across with <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign" rel="nofollow noreferrer">Object.assign</a> could work since the input objects are known to be simple/boring JSON-able <code>Object</code>s... Still needs polyfill on IE, but maybe is a bit more standard?</li>
  </ul>
  <p>The thing is, even if these methods are viable, I can't see how they might be implemented in a way that keeps TypeScript happy?</p>
  <p>For e.g:</p>
  <pre class="lang-js prettyprint-override"><code>class MyCoolBox implements InputBox {
    constructor(box: InputBox) {
      Object.assign(this, box);
    }
  
    getBottom() {
      return this.top + this.height;
    }
  }
  // &gt; Class 'MyCoolBox' incorrectly implements interface 'InputBox'.
  // (and doesn't recognise presence of .top, .height)
  
  Object.setPrototypeOf(inputObj.box, MyCoolBox);
  inputObj.box.getBottom();
  // &gt; Property 'getBottom' does not exist on type 'InputBox'
  // Doesn't recognise the change of interface.
  </code></pre>
  <p>Am I missing some sensible way to do this that TypeScript could understand? It seems a reasonable ask to just decorate a JSON-parsed object (of known interface) with some methods!</p>