title: Is it possible to precisely type _.invert in TypeScript?
body: <p>In lodash, the <a href="https://lodash.com/docs/4.17.11#invert" rel="noreferrer"><code>_.invert</code></a> function inverts an object's keys and values:</p>
  
  <pre class="lang-js prettyprint-override"><code>var object = { 'a': 'x', 'b': 'y', 'c': 'z' };
  
  _.invert(object);
  // =&gt; { 'x': 'a', 'y': 'b', 'z': 'c' }
  </code></pre>
  
  <p>The lodash typings <a href="https://github.com/DefinitelyTyped/DefinitelyTyped/blob/21e68259f6fd43aba37e8112e3edb792975f8266/types/lodash/common/object.d.ts#L2001" rel="noreferrer">currently</a> declare this to always return a <code>string</code>→<code>string</code> mapping:</p>
  
  <pre class="lang-js prettyprint-override"><code>_.invert(object);  // type is _.Dictionary&lt;string&gt;
  </code></pre>
  
  <p>But sometimes, especially if you're using a <a href="https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions" rel="noreferrer">const assertion</a>, a more precise type would be appropriate:</p>
  
  <pre><code>const o = {
    a: 'x',
    b: 'y',
  } as const;  // type is { readonly a: "x"; readonly b: "y"; }
  _.invert(o);  // type is _.Dictionary&lt;string&gt;
                // but would ideally be { readonly x: "a", readonly y: "b" }
  </code></pre>
  
  <p>Is it possible to get the typings this precise? This declaration gets close:</p>
  
  <pre><code>declare function invert&lt;
    K extends string | number | symbol,
    V extends string | number | symbol,
  &gt;(obj: Record&lt;K, V&gt;): {[k in V]: K};
  
  invert(o);  // type is { x: "a" | "b"; y: "a" | "b"; }
  </code></pre>
  
  <p>The keys are right, but the values are the union of the input keys, i.e. you lose the specificity of the mapping. Is it possible to get this perfect?</p>