title: Advanced interface types for maps (objects) in typescript
body: <p>I am creating a proxy-based system to intercept all reads/writes to a certain model. I am having problems, however, with creating the inerface types the system represents. </p>
  
  <p>The system will, on a read or write to the model, intercept the read/write with a <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy" rel="nofollow noreferrer">proxy</a> and create new proxies accordingly to be able to intercept all future read/write operations. The root (let's call it <code>root</code>) proxy is cast to a type the proxy represents. This may be, for example: </p>
  
  <pre><code>interface Root {
      foo: string;
      bar: Map&lt;OtherType&gt;;
  }
  </code></pre>
  
  <p>where</p>
  
  <pre><code>interface Map&lt;T&gt; {
      [key: string]: T | T[] | (obj: T) =&gt; string;
  
      insert: (obj: T) =&gt; string;
      asArray: T[];
  }
  </code></pre>
  
  <p>The problem lies in the interface <code>Map&lt;T&gt;</code>. I would like the type of the actual map to be just <code>T</code>. I think the problem is that when <code>root.bar[x]</code> is requested where <code>x = insert</code>, the type of the returned object is <code>(obj: T) =&gt; string</code>. However, all keys in the map will be a string of length 8. What i'd actually like to do is something like this: </p>
  
  <pre><code>type ID = string[8]
  
  interface Map&lt;T&gt; {
      [key: ID]: T
  
      insert: (obj: T) =&gt; string;
      asArray: T[];
  }
  </code></pre>
  
  <p>I cannot figure out how to:</p>
  
  <ul>
  <li>create a type ID being a string of length 8</li>
  <li>use an alternative string-type as key (typescript will not allow me to)</li>
  </ul>
  
  <p>I already looked in the typescript declarations file, where the Object type is defined. In this definition they seem to omit the map completely. Is this something that's implemented in the compiler/linter itself?</p>
  
  <p>Does anyone know a fix or workaround to achieve something like this? I think it's pretty ugly to have to cast to a type T every time I do a map lookup. </p>