title: Typescript compiler infering type with generics
body: <p>I try to achieve a generic <code>isEventOfType</code> function. In multiple places events from a x-state statemachine are defined (see <code>Maschine1Events</code>, <code>Maschine2Events</code>). When processing events x-states can only provide a <code>Maschine1Events</code> or <code>Maschine2Events</code> but can't tell exactly which event is processed.</p>
  <p>I therefore need a method to check if the event is of a type that I expect. For example that the 'CHANGE' event is provided.</p>
  <p>This example is fully functional, but what I fail to understand is why inside the <code>fWithoutGeneric</code> function the types can't be infered.</p>
  <pre class="lang-js prettyprint-override"><code>    export type Event&lt;TType, TData = unknown&gt; = { type: TType } &amp; TData;
      export type Value&lt;TType&gt; = { value: TType };
  
      type Maschine1Events = Event&lt;'INC'&gt; | Event&lt;'DEC'&gt; | Event&lt;'CHANGE', Value&lt;number&gt;&gt;;
      type Maschine2Events = Event&lt;'INC', Value&lt;number&gt; | Event&lt;'SEND_MESSAGE', Value&lt;string&gt;&gt;;
  
      type EventTypes&lt;T extends Event&lt;unknown&gt;&gt; = T['type'];
      type EventOfType&lt;T extends Event&lt;unknown&gt;, U extends EventTypes&lt;T&gt; = EventTypes&lt;T&gt;&gt; = Extract&lt;T, { type: U }&gt;;
      function isEventOfType&lt;T extends Event&lt;unknown&gt;, U extends EventTypes&lt;T&gt; = EventTypes&lt;T&gt;&gt;(
          event: T,
          type: U
      ): event is EventOfType&lt;T, U&gt; {
          return event.type === type;
      }
  
      function fWithGenerics(event: Maschine1Events) {
          if (isEventOfType&lt;Maschine1Events, 'CHANGE'&gt;(event, 'CHANGE')) {
              const a: Event&lt;'CHANGE', Value&lt;number&gt;&gt; = event;
          }
      }
      function fWithOutGenerics(event: Maschine2Events) {
          if (isEventOfType(event, 'SEND_MESSAGE')) {
              const a: Event&lt;'SEND_MESSAGE', Value&lt;string&gt;&gt; = event; //Why can't this be infered
          }
      }
  </code></pre>
  <p><a href="https://www.typescriptlang.org/play?ts=4.0.2#code/HYQwtgpgzgDiDGEAEBNJBvAsAKCU0ksCyAGhjnnhAB4wD2ATgC5JMCeMyAogG4TBMAPABVhHCABokwgCIgmIJAF4kAV2ABrYHQDuwAHzKMrcQC5pYzkgC%20SAGTS5CgNwVKNesxNWAaiAA2qhAilhCGKuhIPAFB5qLiNq7YbnjsVgCyIFDwABYAlsAQAIy8-ExQRqUCggDkAJIAcgDCNYYAPkhVQjUyXC3tnXzVNU0AEgCCDQDiXDVSfoHBwKpgAEYQDPr6SZTeyJnZ%20YUATF0VKl21jS3zMUsr65tIHZc1AMpcDTIA%20ulcb29xjM5kgFkFBFAmAwCgBzLZJFJ7QZlUJQERIGhMfgAEwql3UWl0BnC0gA2jU0hAagBdHaUSnIgQAeQAZqF0ZicXihkICdo9PopABVDHULHAXGMpiokQkroy4RbSpihgIITCKSRSnmEXWbaIlnqeBMPJ0YBIPJQLqs9nCUXiyX4zT8gzC%201cqUKuU8r36AAUiN2EB5cQkgfpZiQQsRAEpzMGyhbuWUbeIRMLDFhcLtKAwIExVAxzQmBAA6BlKSt7Ol4aw4A1Gk1mpAsgDqeSYOSm-A2eXgUD9JaY5gOuQKxTOMfI2ZzFpZSD9lutbLTo6OE55UCkIwm01m-qH27Gk2BManWdns-gZshSBA5lex73ILB9zWGyVKiHNZzdZnNgbYBjVNc02w7HImVUJhu0KaF%200HEMkDXcdTk3c9wzwPJ50XK0eVTTgELKbcPi%20X5-kBU90P-S8kGvYBb3vKVahIn4-gBIFZluRYIShWFPwxHlnCQAB6YTWxyNhaJAYAKVYfIKnWC1gBZDYIGxDCAP-P9axwawgA" rel="nofollow noreferrer">Playground link to code</a></p>