npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, πŸ‘‹, I’m Ryan HefnerΒ  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you πŸ™

Β© 2026 – Pkg Stats / Ryan Hefner

@typesugar/testing

v0.1.0

Published

🧊 Compile-time testing macros β€” power assertions, property-based testing, type assertions

Readme

@typesugar/testing

Compile-time testing macros β€” power assertions, property-based testing, and more.

Overview

@typesugar/testing provides compile-time testing superpowers: power assertions with sub-expression capture, compile-time assertions that fail the build, parameterized tests, snapshot testing with source capture, and property-based testing.

Installation

npm install @typesugar/testing
# or
pnpm add @typesugar/testing

Quick Start

import {
  assert, // Power assertions with sub-expression capture
  staticAssert, // Compile-time assertions (fail BUILD, not test)
  typeAssert, // Type-level assertions
  type Equal, // Type equality check
  type Extends, // Type extends check
} from "@typesugar/testing";

// Runtime assertion β€” captures sub-expression values on failure
assert(users.length === expected.length);

// Compile-time assertion β€” fails the BUILD if false
staticAssert(CONFIG.TIMEOUT > 0, "timeout must be positive");

// Type assertion β€” verifies types at compile time
typeAssert<Equal<ReturnType<typeof parse>, AST>>();

Usage

assert() β€” Power Assertions

On failure, shows the value of every sub-expression.

import { assert } from "@typesugar/testing";

assert(users.length === filtered.length);

// On failure:
//   Power Assert Failed
//
//   users.length === filtered.length
//
//   Sub-expressions:
//     users.length === filtered.length β†’ false
//     users.length β†’ 3
//     users β†’ [{...}, {...}, {...}]
//     filtered.length β†’ 2
//     filtered β†’ [{...}, {...}]

staticAssert() β€” Compile-Time Assertions

Fail the BUILD, not the test. Zero runtime cost.

import { staticAssert } from "@typesugar/testing";

staticAssert(3 + 4 === 7, "basic math must work");
staticAssert(SUPPORTED_LOCALES.length > 0, "must have locales");

// If false: BUILD FAILS with the message
// If true: No runtime cost (expands to void 0)

typeAssert() β€” Type-Level Assertions

Verify type relationships at compile time.

import { typeAssert, Equal, Extends } from "@typesugar/testing";

typeAssert<Equal<1 + 1, 2>>();
typeAssert<Extends<"hello", string>>();
typeAssert<Equal<ReturnType<typeof parse>, AST>>();

// Build fails if type doesn't match

@testCases() β€” Parameterized Tests

Expand one test function into multiple cases.

import { testCases } from "@typesugar/testing";

@testCases([
  { input: "", expected: true },
  { input: "hello", expected: false },
  { input: "  ", expected: true },
])
function testIsBlank(input: string, expected: boolean) {
  expect(isBlank(input)).toBe(expected);
}

// Expands to:
// it('testIsBlank (case #1: input="", expected=true)', ...)
// it('testIsBlank (case #2: input="hello", expected=false)', ...)
// it('testIsBlank (case #3: input="  ", expected=true)', ...)

assertSnapshot() β€” Source-Capturing Snapshots

Snapshot testing with compile-time source capture.

import { assertSnapshot } from "@typesugar/testing";

assertSnapshot(formatUser(testUser));
// Label: "file.ts:42 β€” formatUser(testUser)"

assertSnapshot(renderComponent(props), "dark mode");
// Label: "file.ts:45 β€” renderComponent(props) [dark mode]"

forAll() β€” Property-Based Testing

Test properties with auto-generated values.

import { forAll } from "@typesugar/testing";
import { derive } from "@typesugar/derive";

@derive(Arbitrary)
interface User {
  name: string;
  age: number;
  active: boolean;
}

// Test that serialization round-trips
forAll(arbitraryUser, (user) => {
  expect(deserialize(serialize(user))).toEqual(user);
});

// With custom iteration count
forAll(arbitraryUser, 500, (user) => {
  expect(user.age).toBeGreaterThanOrEqual(0);
});

// On failure:
//   Property failed after 42 tests.
//   Failing input: {"name":"...","age":-1,...}
//   Error: Expected age >= 0

Type Utilities

import {
  Equal, // Type equality
  Extends, // Subtype check
  Not, // Negation
  And, // Conjunction
  Or, // Disjunction
  IsNever, // Check for never
  IsAny, // Check for any
  IsUnknown, // Check for unknown
} from "@typesugar/testing";

// Use with typeAssert
typeAssert<Equal<A, B>>();
typeAssert<Extends<Child, Parent>>();
typeAssert<Not<IsAny<T>>>();
typeAssert<And<Extends<A, B>, Extends<B, C>>>();

Examples

See the examples/ directory for real-world patterns:

  • basic.ts β€” Core testing patterns from dogfooding typesugar's own test suite

API Reference

Assertions

  • assert(condition, message?) β€” Assert with sub-expression capture
  • staticAssert(condition, message?) β€” Compile-time assertion
  • typeAssert<T extends true>() β€” Type-level assertion
  • assertSnapshot(value, name?) β€” Snapshot with source capture

Deprecated Aliases

  • powerAssert β€” Use assert() instead
  • comptimeAssert β€” Use staticAssert() instead

Parameterized Testing

  • @testCases(cases) β€” Expand to multiple test cases

Property-Based Testing

  • forAll(generator, property) β€” Test property with 100 iterations
  • forAll(generator, count, property) β€” Test property with custom count

Type Utilities

  • Equal<A, B> β€” True if A and B are the same type
  • Extends<A, B> β€” True if A extends B
  • Not<T> β€” Negate a boolean type
  • And<A, B> β€” Conjunction of boolean types
  • Or<A, B> β€” Disjunction of boolean types
  • IsNever<T> β€” True if T is never
  • IsAny<T> β€” True if T is any
  • IsUnknown<T> β€” True if T is unknown

Vitest Integration

To use @typesugar/testing macros in your vitest tests, add the typesugar transformer plugin to your vitest.config.ts:

import { defineConfig } from "vitest/config";
import typemacro from "unplugin-typesugar/vite";

export default defineConfig({
  plugins: [typemacro()],
  test: {
    // your test config
  },
});

Then import and use the macros in your test files:

import { describe, it } from "vitest";
import { assert, typeAssert, type Equal } from "@typesugar/testing";

describe("my tests", () => {
  it("uses power assertions", () => {
    assert(result.status === "success");
  });

  it("verifies types", () => {
    typeAssert<Equal<typeof result, MyType>>();
  });
});

License

MIT