Core functionality for performing type equality checks, object matching, and type extension validation with precise control over type relationships.
Performs exact type equality checks using TypeScript's internal type identity mechanism.
/**
* Uses TypeScript's internal technique to check for type "identicalness"
* Checks if types are fully equal to each other
* @param value - Optional value to infer type from
* @returns true if types match exactly
*/
toEqualTypeOf<Expected>(): true;
toEqualTypeOf<Expected>(value: Expected): true;Usage Examples:
import { expectTypeOf } from "expect-type";
// Generic type argument syntax (recommended for better error messages)
expectTypeOf({ a: 1 }).toEqualTypeOf<{ a: number }>();
// Inferred type syntax
expectTypeOf({ a: 1 }).toEqualTypeOf({ a: 2 }); // different values, same type
// Fails on excess properties
// @ts-expect-error
expectTypeOf({ a: 1, b: 2 }).toEqualTypeOf<{ a: number }>();
// Fails on missing properties
// @ts-expect-error
expectTypeOf({ a: 1 }).toEqualTypeOf<{ a: number; b: string }>();Performs strict checking on a subset of object properties, allowing extra properties on the actual type.
/**
* Similar to jest's expect(...).toMatchObject(...) but for types
* Deeply "picks" properties of actual type based on expected type
* @param MISMATCH - Mismatch arguments for error handling
* @returns true if object structure matches
*/
toMatchObjectType<Expected>(...MISMATCH: MismatchArgs): true;Usage Examples:
import { expectTypeOf } from "expect-type";
// Allow extra properties
expectTypeOf({ a: 1, b: 2 }).toMatchObjectType<{ a: number }>();
// Works with deeply nested objects
const user = {
name: "John",
email: "john@example.com",
address: {
street: "123 Main St",
city: "New York",
country: "USA"
}
};
expectTypeOf(user).toMatchObjectType<{
name: string;
address: { city: string };
}>();
// Fails on missing properties
// @ts-expect-error
expectTypeOf({ a: 1 }).toMatchObjectType<{ a: number; b: string }>();Checks if one type extends another, useful for "is-a" relationships and assignability.
/**
* Check if your type extends the expected type
* Less strict version that allows for extra properties
* Equivalent to an extends constraint in a function type argument
* @param MISMATCH - Mismatch arguments for error handling
* @returns true if type extends expected
*/
toExtend<Expected>(...MISMATCH: MismatchArgs): true;Usage Examples:
import { expectTypeOf } from "expect-type";
// Basic extension check
expectTypeOf("hello").toExtend<string>();
expectTypeOf("hello").toExtend<string | number>();
// Object extension
expectTypeOf({ a: 1, b: 2 }).toExtend<{ a: number }>();
// Type hierarchy example
type Fruit = { type: 'Fruit'; edible: boolean };
type Apple = { type: 'Fruit'; name: 'Apple'; edible: true };
expectTypeOf<Apple>().toExtend<Fruit>(); // Apple is a Fruit
expectTypeOf<Fruit>().not.toExtend<Apple>(); // but not vice versa
// Fails on incompatible types
// @ts-expect-error
expectTypeOf({ a: 1 }).toExtend<{ b: number }>();Alternative equality check that handles intersection types more permissively but with performance cost.
/**
* More permissive but less performant equality check
* Accommodates for equivalent intersection types
* @param MISMATCH - Mismatch arguments for error handling
* @returns true if types are equivalent under branding
*/
branded: {
toEqualTypeOf<Expected>(...MISMATCH: MismatchArgs): true;
};Usage Examples:
import { expectTypeOf } from "expect-type";
// Regular toEqualTypeOf fails with intersection types
// @ts-expect-error
expectTypeOf<{ a: 1 } & { b: 2 }>().toEqualTypeOf<{ a: 1; b: 2 }>();
// But branded version works
expectTypeOf<{ a: 1 } & { b: 2 }>().branded.toEqualTypeOf<{ a: 1; b: 2 }>();
// Works with nested intersections
expectTypeOf<{ a: { b: 1 } & { c: 1 } }>()
.branded.toEqualTypeOf<{ a: { b: 1; c: 1 } }>();All type equality and matching methods support negation via the .not property.
/**
* Inverts the result of following assertions
*/
not: NegativeExpectTypeOf<Actual>;Usage Examples:
import { expectTypeOf } from "expect-type";
// Negated equality
expectTypeOf({ a: 1 }).not.toEqualTypeOf<{ b: number }>();
// Negated matching
expectTypeOf({ a: 1 }).not.toMatchObjectType<{ b: number }>();
// Negated extension
expectTypeOf({ a: 1 }).not.toExtend<{ b: number }>();
// Useful for type hierarchy validation
type Fruit = { type: 'Fruit'; edible: boolean };
type Apple = { type: 'Fruit'; name: 'Apple'; edible: true };
expectTypeOf<Apple>().toExtend<Fruit>();
expectTypeOf<Fruit>().not.toExtend<Apple>();
expectTypeOf<Apple>().not.toEqualTypeOf<Fruit>();/**
* @deprecated Since v1.2.0 - Use either toMatchObjectType or toExtend instead
* Legacy method for type matching - use toMatchObjectType for strict subset checks
* or toExtend for assignability checks
*/
toMatchTypeOf<Expected>(): true;
toMatchTypeOf<Expected>(value: Expected): true;Migration Examples:
import { expectTypeOf } from "expect-type";
// Old (deprecated)
expectTypeOf({ a: 1, b: 2 }).toMatchTypeOf<{ a: number }>();
// New (recommended)
expectTypeOf({ a: 1, b: 2 }).toMatchObjectType<{ a: number }>(); // for strict object matching
expectTypeOf({ a: 1, b: 2 }).toExtend<{ a: number }>(); // for assignabilityType mismatch errors provide detailed information about expected vs actual types:
// This will show: Expected: string, Actual: number
expectTypeOf({ a: 1 }).toEqualTypeOf<{ a: string }>();For better error messages, prefer generic type argument syntax over value inference when possible.