title: Typescript type safety in switch case statements
body: <p>I'm working with Redux and I'm trying to make my reducers type safe. I found some code example from the ngrx-store/example app where they perfectly succeed in doing this. (<a href="https://github.com/ngrx/example-app/blob/master/src/app/actions/book.ts" rel="noreferrer">https://github.com/ngrx/example-app/blob/master/src/app/actions/book.ts</a>)</p>
  
  <p>While integrating this in my own project, I noticed something strange, which I cannot explain. Check the following code sample (some comments inline):</p>
  
  <pre><code>// Action has a type and payload property
  interface Action {
      type: string;
      payload?: any;
  }
  
  // Here I declare the action types as plain strings
  const FIRST = "FIRST";
  const SECOND = "SECOND";
  
  // I create classes for every action with there respective types
  class FirstAction implements Action {
      public type = FIRST;
      payload: { id: number };
  
      public constructor(id: number) {
          this.payload = { id };
      }
  }
  
  class SecondAction implements Action {
      public type = SECOND;
  
      public constructor() { }
  }
  
  // Create a union type
  type Actions = FirstAction | SecondAction;
  
  // Use the union type as type parameter in my function
  function test(action: Actions): void {
      switch (action.type) {
          case FIRST:
                      // compiler will complain it cannot find the payload 
                      // property on Actions
              let temp = action.payload.id;
          case SECOND:
          // empty
          default:
          //empty
      }
  }
  </code></pre>
  
  <p>If I replace the definition of the FIRST and SECOND properties into the following, it does work.</p>
  
  <pre><code>export function type&lt;T&gt;(label: T | ''): T {
      return &lt;T&gt;label;
  }
  
  
  const FIRST = type("FIRST");
  const SECOND = type("SECOND");
  </code></pre>
  
  <p>As far as I can see, the type function only casts the string back to a string. Why does the code work with calling the <code>type</code> function but not when declaring the strings immediately?</p>
  
  <p>Here's a <a href="http://www.typescriptlang.org/play/#src=interface%20Action%20%7B%0D%0A%09type:%20string;%0D%0A%09payload?:%20any;%0D%0A%7D%0D%0A%0D%0Aexport%20function%20type%3CT%3E(label:%20T%20%7C%20&#39;&#39;):%20T%20%7B%0D%0A%09return%20%3CT%3Elabel;%0D%0A%7D%0D%0A%0D%0Aconst%20FIRST%20=%20type(%22FIRST%22);%0D%0Aconst%20SECOND%20=%20type(%22SECOND%22);%0D%0A%0D%0A//const%20FIRST%20=%20%22FIRST%22;%0D%0A//const%20SECOND%20=%20%22SECOND%22;%0D%0A%0D%0Aclass%20FirstAction%20implements%20Action%20%7B%0D%0A%09public%20type%20=%20FIRST;%0D%0A%09payload:%20%7B%20id:%20number%20%7D;%0D%0A%0D%0A%09public%20constructor(id:%20number)%20%7B%0D%0A%09%09this.payload%20=%20%7B%20id%20%7D;%0D%0A%09%7D%0D%0A%7D%0D%0A%0D%0Aclass%20SecondAction%20implements%20Action%20%7B%0D%0A%09public%20type%20=%20SECOND;%0D%0A%0D%0A%09public%20constructor()%20%7B%20%7D%0D%0A%7D%0D%0A%0D%0Atype%20Actions%20=%20FirstAction%20%7C%20SecondAction;%0D%0A%0D%0Afunction%20test(action:%20Actions):%20void%20%7B%0D%0A%09switch%20(action.type)%20%7B%0D%0A%09%09case%20FIRST:%0D%0A%09%09%09let%20temp%20=%20action.payload.id;%0D%0A%09%09case%20SECOND:%0D%0A%09%09//%20empty%0D%0A%09%09default:%0D%0A%09%09//empty%0D%0A%09%7D%0D%0A%7D%0D%0A" rel="noreferrer">typescript playground example</a> where you can just comment the definitons in or out (first with the working version).</p>