Search code examples
typescripttypesngrx

Typescript: Find Type Group


I have a a few types:

type A = A1 | A2 | A3;

type B = B1 | B2 | B3;

type AnyType = A | B;

All the types (A1, A2, A3, B1, B2, B3) are classes.

There's also a function which receives an AnyType called action:

function myReducerFunction(action: AnyType) {
  // Does action belong to A or B here?
}

I'm building a reducer with NgRx and I'd like to split the switch statement into more manageable blocks. Hence, depending on whether action is any of A or any of B I'd return whatever a "subreducer" returns, instead of handling it all in one big function.

So, how can I know if something is an A or a B inside that function?

Would it make more sense to use interfaces instead of types? If it would, could it be done with types anyway, and how?


Solution

  • Typescript's types don't exist during runtime, so you'll need to use plain JS to decide what type your action is.

    Since A1-3 and B1-3 are classes, this can easily be done with instanceof. Combined with a type predicate you can build something like:

    function isTypeA(val: AnyType): val is A {
      return [A1, A2, A3].some(clazz => val instanceof clazz);
    
    }
    
    function isTypeB(val: AnyType): val is B {
      return [B1, B2, B3].some(clazz => val instanceof clazz);
    }
    
    function myReducerFunction(action: AnyType) {
      if (isTypeA(action)) {
        // TS will now assume action is of type A.
      } else {
        // TS will now assume action is of type B.
        // You might not even need `isTypeB` since TS will be smart enough to realize 
        // `action` can only be type B here.
      }
    }
    

    With type predicates, you'll be able to access properties exclusive to A1-3 or B1-3 without Typescript complaining!