Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit test typescript types

I have the following export in one of my modules:

export class Action1 implements Action {}

export class Action2 implements Action {}

export type ActionsUnion =
  | Action1
  | Action2;

I am trying to work out the best way to test ActionsUnion to make sure it is of the types I have defined. For example:

it('should have the correct types', () => {
  expect(typeof Action1).toEqual(ActionsUnion);
  expect(typeof Action2).toEqual(ActionsUnion);
});

Of course the above doesn't work as I am using ActionsUnion as a variable. Any ideas on how to achieve the above?

For context, I am using angular, ngrx and jasmine.

like image 461
Ian Jamieson Avatar asked Sep 05 '25 15:09

Ian Jamieson


1 Answers

tsafe enables to unit test types, example:

// This test file is not meant to be executed, if there is not TS errors, it passes.


import { assert, Equals } from "tsafe";

declare function myFunction<T extends string>(arr: T[]): T;

{

  const got = myFunction([ "a", "b", "c" ]);

  type Got = typeof got;

  type Expect = "a" | "b";

  // Here we have a TS error, as we should, because:
  // Got is        "a" | "b" | "c"
  // and Expect is "a" | "b"
  assert<Equals<Got, Expect>>();

}

{

  const got = myFunction([ "a", "b", "c" ]);

  type Got = typeof got;

  type Expect = "a" | "b" | "c";

  // ✅ Got and Expect are the same type
  assert<Equals<Got, Expect>>();

}

{

  //@ts-expect-error: We shouldn't be allowed to pass numbers
  myFunction([ "a", 42, "c" ]);

}

{

    // Here we got some red because we say we expect an 
    // error but the expression is valid
    //@ts-expect-error
    myFunction([ "a", "b", "c" ]);

}

{

  const got = myFunction([ "a", "b", "c" ]);

  type Got = typeof got;


  // We can also validate that 
  assert<Got extends string ? true : false>();


}

{

  type T = "a" | "b";
  type U = string;

  // We expect that T extends U
  assert<T extends U ? true : false>();

}

In the example of the question:

import { assert } from "tsafe/assert";
import type { Extends } from "tsafe";

type Action= { _signature: undefined; }

 class Action1 implements Action {
   _signature: undefined;
 }

 class Action2 implements Action {
  _signature: undefined;
 }

export type ActionsUnion =
  | Action1
  | Action2;

assert<Extends<Action1, ActionsUnion>>();

Disclosure: I am the author.

like image 175
Joseph Garrone Avatar answered Sep 08 '25 06:09

Joseph Garrone