title: typescript cannot infer subset of keys of object from usage
body: <p>I'm working on algebraic data types in ts and stuck with typing the match function. Simplified version of the problem is demonstrated below:</p>
  
  <pre><code>let rec = { a: 'a', b: 1 };
  
  // just captures type of 'rec' and then reuses the type for eval
  const makeEval = &lt;Record&gt;(rec: Record) =&gt; &lt;
    Res,
    K extends keyof Record = keyof Record
  &gt;(
    val: Record,
    cases:
      | Cases&lt;Record, Res&gt;
      | (Cases&lt;Record, Res, K&gt; &amp; { else: (r: Record) =&gt; Res })
  ): Res =&gt; (undefined as any) as Res;
  
  export type Cases&lt;Record, Res, K extends keyof Record = keyof Record&gt; = {
    [T in K]: (value: Record[T]) =&gt; Res
  };
  
  const evalMyRecord = makeEval(rec);
  
  // this is fine
  const a = evalMyRecord(rec, { a: s =&gt; s, b: n =&gt; n.toString() });
  
  // err
  const b = evalMyRecord(rec, { a: s =&gt; s, else: _ =&gt; 'why err?' });
  // Property 'b' is missing in type '{ a: (s: string) =&gt; string; else: (_: { a: string; b: number; }) =&gt; string; }'.
  
  // requires explicit subset
  const b_ = evalMyRecord&lt;string, 'a'&gt;(rec, {
    a: s =&gt; s,
    else: _ =&gt; 'but explicit a is fine'
  });
  
  // full set is fine
  const c = evalMyRecord(rec, {
    a: s =&gt; s,
    b: n =&gt; 'n',
    else: _ =&gt; 'fine too'
  });
  </code></pre>
  
  <p>So I want to express a type that is either has all keys of Record or any subset of it + {else} case.</p>
  
  <p>I know that there is a solution with Partial:</p>
  
  <pre><code>type EvalCases&lt;Record, Res&gt; =
    | Cases&lt;Record, Res&gt;
    | (Partial&lt;Cases&lt;Record, Res&gt;&gt; &amp; { else: (r: Record) =&gt; Res });
  
  const b = evalMyRecord(rec, { a: s =&gt; s, else: _ =&gt; 'works' });
  
  const b2 = evalMyRecord(rec, {
    a: s =&gt; s,
    b: undefined,
    else: _ =&gt; 'also works but weird'
  });
  </code></pre>
  
  <p>But having: {b: undefined} looks a bit off. I want a compiler error if any case is not a proper function (if possible).</p>
  
  <p>Any suggestions on typescript magic?</p>
  
  <p>NOTE: conceptually close (but no the same) to <a href="https://stackoverflow.com/questions/49014814/typescript-cannot-infer-correct-argument-types-for-an-object-of-functions">Typescript cannot infer correct argument types for an object of functions</a>. </p>