How to add type check assertions in Vitest

21 September 2025
#testing#vitest#typescript#frontend

Sometimes it can be really important that you are able to test your types. For example, if you are publishing a package you might want to ensure the types that you publish match types used elsewhere in your system.

This is really easy with Vitest!

What is meant by type check tests?

So if you have a TypeScript app, you probably have a step in your CI/CD which checks that all the types in your app match.

If you had this for example, it would fail:

// the :string tells typescript this will return a string...
function doesntReturnAString(): string {
  return 1; // << not a string!
}

I think most apps nowadays have these sorts of checks already.

But sometimes you might be writing complex types or functions that return a mix of generic types, and you want to assert that these are working correctly.

For example you might assert that some public API on a service's getUser() has the correct parameter types and return type:

test('API backward compatibility', () => {
  expectTypeOf<UserService['getUser']>().parameter(0).toEqualTypeOf<{
    id: string;
    includeDeleted?: boolean;
  }>();

  expectTypeOf<UserService['getUser']>().returns.toEqualTypeOf<Promise<User | null>>();
});

Or even test your complex generics:

type ExtractParams<T> = T extends (...args: infer P) => any ? P : never;

test('generic ExtractParams return expected types', () => {
  type TestFn = (a: string, b: number, c: boolean) => void;

  expectTypeOf<ExtractParams<TestFn>>().toEqualTypeOf<[string, number, boolean]>();
  expectTypeOf<ExtractParams<string>>().toEqualTypeOf<never>();
  expectTypeOf<ExtractParams<() => void>>().toEqualTypeOf<[]>();
});

How to start using Vitest type checks:

Under the hood, it uses the expect-type package. Getting it working in Vitest is easy though:

Step 1: Create a new file, called something.test-d.ts

For type checks in Vitest, by default it has to have the .test-d.ts suffix .

Step 2: Then import the helper functions:

import { assertType, expectTypeOf } from 'vitest';

Step 3: Write your assertions

The type assertions are done via TSC, so you can use a mix of the vitest functions, along with generics.

import { expect, expectTypeOf, test } from 'vitest';

function returnAny() {
  return 'abc' as any;
}

const blogPost = {
  title: 'some blog post',
  tags: ['tag1', 'tag2'],
  body: 'here is the blog post',
};

test('type checks', () => {
  // both are number, so they're equal types
  expectTypeOf(1).toEqualTypeOf(2);

  expectTypeOf('hello').toBeString();

  expectTypeOf([]).toBeArray();

  expectTypeOf(returnAny()).toBeAny();

  expectTypeOf(blogPost).toEqualTypeOf<{
    title: string;
    tags: string[];
    body: string;
  }>();

  expectTypeOf('some string').toExtend<string | number>();

  expectTypeOf({
    a: 1,
    b: 2,
  }).toExtend<{ a: number }>();
});

Step 4: run type checks in vitest

You have to add the --typecheck flag when running vitest:

{
  "scripts": {
    "test": "vitest",
    "test:types": "vitest --typecheck --run"
  }
}

Then you can run npm run test:types, yarn test:types or pnpm test:types

Note: you can also set "test": "vitest --typecheck" to do 'normal' tests and type check tests together, when you run npm run test.

Examples

Simple assertions

Use the assertType() function - pass in the value, and the expected type as a generic:

import { assertType } from 'vitest';

test('some simple tests', () => {
  const someNumber = 123;
  assertType<number>(someNumber);

  const greeting = 'Hello';
  assertType<string>(greeting);
});

Use expectTypeOf for similar fluent syntax like expect()

import { expectTypeOf, test } from 'vitest';

test('expectTypeOf examples', () => {
  const user = {
    id: '123',
    name: 'Bart Simpson',
    email: 'helllo@example.com',
    age: 50,
  };

  expectTypeOf(user).toEqualTypeOf<{
    id: string;
    name: string;
    email: string;
    age: number;
  }>();

  expectTypeOf(user).toExtend<{
    id: string;
  }>();

  expectTypeOf(user.name).toBeString();
  expectTypeOf(user.age).toBeNumber();
  expectTypeOf(['a', 'b', 'c']).toBeArray();
});

Checking for type errors

Sometimes you might want to assert that a type is not valid:

const someNumber = 99;

// @ts-expect-error someNumber is not a string
assertType<string>(someNumber);

Tips

  • You cannot use test.each() to iterate over test cases.
  • You can nest the tests in describe() blocks just like regular tests
  • Remember to test the negative case. All of your tests could pass if somewhere along the way any was set as a type - so make sure to check something is failing type checks (with @ts-expect-error).
  • Read through expect-type to understand this powerful feature

Have a play

Here is the official playground to interact and try out Vitest type check tests. View it here

Found this useful? Share this article

TwitterLinkedIn Facebook

🎯 Become the best at testing FE apps: Get exclusive testing tips & tricks delivered to your inbox

Stop wasting hours debugging flaky tests. Join hundreds of developers who get practical, battle-tested testing strategies straight to their inbox.

Every issue includes real-world code examples, Vitest best practices (including Vitest Browser Mode), testing patterns that actually work, and e2e testing strategies you can implement immediately.

✨ No fluff. Just actionable tips that make your tests better.

✅ Free forever✅ No spam✅ Unsubscribe anytime

Sent every 2-3 weeks. I respect your inbox and your time. Each email is packed with value, not filler.

I have courses on how to test frontend apps. Want to join?

Practical, interactive lessons that help you ship with confidence and become the expert on your team at understanding how to test frontend apps correctly.

Join the courses →