Skip to content
Advertisement

Check if type of emitted variable matches custom type

I am testing some Vue 3 components with jest and expect to get an emit when a button is clicked. Now I want to check if the object emitted matches a custom type I created in a different file. e.g.:

//types.ts
export type customType = {
  foo: string;
  bar: {
    foobar: number;
    barfoo: number;
  };
}

My test case looks something like this:

//Component.spec.js
it("tests if types match", () => {
  const wrapper = [...];

  // do some stuff to get this event emitted

  expect(typeof wrapper.emitted().customEvent).toBe(customType);
});

But here I get the error Element is not accessible at customType even though I am importing it.

How can I check if the variable emitted with my custom event matches my custom type?

Answer

The reason you’re seeing this is because Jest’s expect is not type aware, as tests are compiled to JavaScript at runtime.

You have two possible approaches:

A. If you really want to assess custom types at compile time, use expect-type package

import { expectTypeOf } from 'expect-type'

expectTypeOf(wrapper.emitted().customEvent).toEqualTypeOf<customType>()

Under the hood, it’s still using JavaScript, similar to B.2. below, except you don’t need to write the function yourself, it’s generated on the fly, from the provided type.

Note there are differences between toMatchTypeOf and toEqualTypeOf (latter is stricter – e.g: fails on extra props).


B. Stick to JavaScript, with the following alternatives:

B.1. Simplest solution would be to check the actual value:

expect(wrapper.emitted().customEvent).toEqual(someValue)
// I'm guessing you know the value in the test

B.2. Alternatively, you can make a function taking the value as param and checking all of the required props of your type. e.g:

const checkCustomEvent = event => 
  typeof event?.foo === 'string' &&
  [event?.bar?.barfoo, event?.bar?.foobar]
    .every(el => typeof el === 'number');

expect(checkCustomEvent(wrapper.emitted().customEvent)).toBe(true)

B.3. Yet another alternative (I personally don’t like it and rarely use it), would be to change your customType to be a class. At which point you can check:

expect(wrapper.emitted().customEvent instanceof SomeClass).toBe(true)
// or 
expect(wrapper.emitted().customEvent).toBeInstanceOf(SomeClass)

I personally prefer the first js method (B.1.) most times. If I have dynamic results and it makes sense to write a type guard function to check them all, I might do that (B.2.).


Side note: I doubt an emitted()[someKey]‘s value will ever be an object. According to docs it would be an array of arrays: Array<Array<any>>. You probably want to use wrapper.emitted().customEvent[0][0], not wrapper.emitted().customEvent

Advertisement