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

functions.mddocs/

Function Type Analysis

Comprehensive function type checking including parameters, return types, overloads, callability, and constructor analysis.

Capabilities

Function Parameters

Extract and validate individual function parameters and parameter tuples.

/**
 * Extract a specific function parameter by index
 * @param index - Zero-based parameter index
 * @returns ExpectTypeOf for the parameter type at the given index
 */
parameter<Index extends number>(index: Index): ExpectTypeOf<OverloadParameters<Actual>[Index], Options>;

/**
 * Extract all function parameters as a tuple
 * For overloaded functions, returns union of all parameter tuples
 */
parameters: ExpectTypeOf<OverloadParameters<Actual>, Options>;

Usage Examples:

import { expectTypeOf } from "expect-type";

// Single parameter function
const add = (a: number, b: number) => a + b;

expectTypeOf(add).parameter(0).toBeNumber();
expectTypeOf(add).parameter(1).toBeNumber();
expectTypeOf(add).parameters.toEqualTypeOf<[number, number]>();

// No parameter function
const noArgs = () => "hello";
expectTypeOf(noArgs).parameters.toEqualTypeOf<[]>();

// Optional parameters
const withOptional = (required: string, optional?: number) => ({ required, optional });
expectTypeOf(withOptional).parameters.toEqualTypeOf<[string, number?]>();

// Rest parameters
const withRest = (first: string, ...rest: number[]) => ({ first, rest });
expectTypeOf(withRest).parameters.toEqualTypeOf<[string, ...number[]]>();

Function Return Types

Analyze function return types with support for overloaded functions.

/**
 * Extract function return type
 * For overloaded functions, returns union of all return types
 */
returns: ExpectTypeOf<OverloadReturnTypes<Actual>, Options>;

Usage Examples:

import { expectTypeOf } from "expect-type";

// Basic return type
const getString = () => "hello";
expectTypeOf(getString).returns.toBeString();

// Function returning computed type
const getArray = (x: number) => [x, x];
expectTypeOf(getArray).returns.toEqualTypeOf<[number, number]>();

// Void return
const logMessage = (msg: string) => console.log(msg);
expectTypeOf(logMessage).returns.toBeVoid();

// Never return (functions that throw)
const throwError = (): never => { throw new Error("fail"); };
expectTypeOf(throwError).returns.toBeNever();

// Async function returns
const asyncFn = async () => 42;
expectTypeOf(asyncFn).returns.resolves.toBeNumber();

Function Callability

Test whether functions can be called with specific argument types.

/**
 * Check if function is callable with given parameters
 * Returns narrowed type for overloaded functions
 * Note: Cannot be negated with .not - use @ts-expect-error instead
 * @param args - Arguments to test callability with
 * @returns ExpectTypeOf for the narrowed function type
 */
toBeCallableWith<Args extends OverloadParameters<Actual>>(
  ...args: Args
): ExpectTypeOf<OverloadsNarrowedByParameters<Actual, Args>, Options>;

Usage Examples:

import { expectTypeOf } from "expect-type";

// Basic callability
const multiply = (a: number, b: number) => a * b;
expectTypeOf(multiply).toBeCallableWith(5, 10);

// Overloaded function callability
type Factorize = {
  (input: number): number[];
  (input: bigint): bigint[];
};

declare const factorize: Factorize;

expectTypeOf(factorize).toBeCallableWith(6);
expectTypeOf(factorize).toBeCallableWith(6n);

// Narrow return type based on parameters
expectTypeOf(factorize)
  .toBeCallableWith(6)
  .returns.toEqualTypeOf<number[]>();

expectTypeOf(factorize)
  .toBeCallableWith(6n)
  .returns.toEqualTypeOf<bigint[]>();

// Complex overload narrowing
type Delete = {
  (path: string): void;
  (paths: string[], options?: { force: boolean }): void;
};

declare const deleteFiles: Delete;

expectTypeOf(deleteFiles)
  .toBeCallableWith("file.txt")
  .parameters.toEqualTypeOf<[string]>();

expectTypeOf(deleteFiles)
  .toBeCallableWith(["file1.txt", "file2.txt"], { force: true })
  .parameters.toEqualTypeOf<[string[], { force: boolean }?]>();

// Invalid calls (use @ts-expect-error)
// @ts-expect-error
expectTypeOf(multiply).toBeCallableWith("invalid");

Constructor Analysis

Analyze class constructors and their parameters.

/**
 * Check if constructor is callable with given parameters
 * @param args - Constructor arguments to test
 * @returns true if constructor is callable with given arguments
 */
toBeConstructibleWith<Args extends ConstructorOverloadParameters<Actual>>(
  ...args: Args
): boolean;

/**
 * Extract constructor parameter types
 * For overloaded constructors, returns union of all parameter tuples
 */
constructorParameters: ExpectTypeOf<ConstructorOverloadParameters<Actual>, Options>;

/**
 * Extract instance type of a constructor
 */
instance: ExpectTypeOf<InstanceType<Actual>, Options>;

Usage Examples:

import { expectTypeOf } from "expect-type";

// Built-in constructor
expectTypeOf(Date).toBeConstructibleWith();
expectTypeOf(Date).toBeConstructibleWith("2023-01-01");
expectTypeOf(Date).toBeConstructibleWith(0);
expectTypeOf(Date).toBeConstructibleWith(new Date());

expectTypeOf(Date).constructorParameters.toEqualTypeOf<
  | []
  | [value: string | number | Date]
  | [year: number, monthIndex: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number]
>();

// Custom class with overloaded constructor
class DatabaseConnection {
  constructor();
  constructor(connectionString: string);
  constructor(options: { host: string; port: number });
  constructor(..._: unknown[]) {}
}

expectTypeOf(DatabaseConnection).toBeConstructibleWith();
expectTypeOf(DatabaseConnection).toBeConstructibleWith("localhost:5432");
expectTypeOf(DatabaseConnection).toBeConstructibleWith({ 
  host: "localhost", 
  port: 5432 
});

// Instance type checking
expectTypeOf(Date).instance.toHaveProperty("toISOString");
expectTypeOf(Array).instance.toHaveProperty("push");
expectTypeOf(Array).instance.toHaveProperty("length");

This Parameter Analysis

Analyze the this parameter type of functions.

/**
 * Extract the this parameter type of a function
 * Equivalent to TypeScript's ThisParameterType utility type
 */
thisParameter: ExpectTypeOf<ThisParameterType<Actual>, Options>;

Usage Examples:

import { expectTypeOf } from "expect-type";

// Function with explicit this parameter
function greet(this: { name: string }, message: string) {
  return `Hello ${this.name}, ${message}`;
}

expectTypeOf(greet).thisParameter.toEqualTypeOf<{ name: string }>();

// Distinguish functions with different this parameters
function greetFormal(
  this: { title: string; name: string }, 
  message: string
) {
  return `Dear ${this.title} ${this.name}, ${message}`;
}

function greetCasual(this: { name: string }, message: string) {
  return `Hi ${this.name}, ${message}`;
}

expectTypeOf(greetFormal).not.toEqualTypeOf(greetCasual);
expectTypeOf(greetFormal).thisParameter.toEqualTypeOf<{ 
  title: string; 
  name: string; 
}>();
expectTypeOf(greetCasual).thisParameter.toEqualTypeOf<{ name: string }>();

// Regular functions without explicit this
const regularFunction = (x: number) => x * 2;
expectTypeOf(regularFunction).thisParameter.toBeUnknown();

Overloaded Functions

Handle function overloads properly, unlike TypeScript's built-in Parameters and ReturnType utilities.

import { expectTypeOf } from "expect-type";

// Overloaded function
type StringOrNumberProcessor = {
  (input: string): string[];
  (input: number): number[];
};

declare const processor: StringOrNumberProcessor;

// expect-type handles all overloads
expectTypeOf(processor).parameters.toEqualTypeOf<[string] | [number]>();
expectTypeOf(processor).returns.toEqualTypeOf<string[] | number[]>();

// TypeScript built-ins only handle last overload
expectTypeOf<Parameters<StringOrNumberProcessor>>().toEqualTypeOf<[number]>();
expectTypeOf<ReturnType<StringOrNumberProcessor>>().toEqualTypeOf<number[]>();

// Access specific overload via parameter narrowing
expectTypeOf(processor).parameter(0).toEqualTypeOf<string | number>();

Type Guards and Assertions

Analyze type guard and assertion functions.

/**
 * Extract the type guarded by a type guard function
 * Works with functions that return `v is T`
 */
guards: ExpectTypeOf<GuardedType, Options>;

/**
 * Extract the type asserted by an assertion function
 * Works with functions that use `asserts v is T`
 */
asserts: ExpectTypeOf<AssertedType, Options>;

Usage Examples:

import { expectTypeOf } from "expect-type";

// Type guard function
function isString(value: unknown): value is string {
  return typeof value === "string";
}

expectTypeOf(isString).guards.toBeString();

function isBigInt(value: unknown): value is bigint {
  return typeof value === "bigint";
}

expectTypeOf(isBigInt).guards.toBeBigInt();

// Assertion function
function assertIsNumber(value: unknown): asserts value is number {
  if (typeof value !== "number") {
    throw new TypeError("Expected number");
  }
}

expectTypeOf(assertIsNumber).asserts.toBeNumber();

// Complex type guards
function isUser(value: unknown): value is { name: string; age: number } {
  return typeof value === "object" && 
         value !== null && 
         "name" in value && 
         "age" in value;
}

expectTypeOf(isUser).guards.toEqualTypeOf<{ name: string; age: number }>();

Limitations

  1. Generic Functions: toBeCallableWith may fail with generic functions. Use type assertions or specific instantiations.

  2. Complex Overloads: Functions with more than 10 overloads may not be fully analyzed.

  3. This References: Cannot pass this directly to expectTypeOf within class methods. Use .instance instead.