or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

advanced-types.mdbasic-types.mdfunctions.mdindex.mdobjects.mdtype-equality.md
tile.json

type-equality.mddocs/

Type Equality and Matching

Core functionality for performing type equality checks, object matching, and type extension validation with precise control over type relationships.

Capabilities

Strict Type Equality

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 }>();

Object Structure Matching

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 }>();

Type Extension Checking

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 }>();

Branded Type Equality

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 } }>();

Negated Assertions

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: Legacy Type Matching

/**
 * @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 assignability

Error Handling

Type 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.