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

lay-sing

v0.4.2

Published

Utilities for compile-time type testing

Downloads

172

Readme

GitHub License NPM Version JSR Version GitHub Actions Workflow Status

Lay-Sing

TypeScript utilities for compile-time type testing and utility types

// They do nothing at runtime
expect<never>().to.be<never>().pass
expect<never>().to.be.never // alias for the above
expect<never>().to.be<'should fail'>().fail

// Type Error: Property 'pass' does not exist on type '{ fail: void; }'.
expect<never>().to.be<'should fail'>().pass
//                                    ^^^^^^^

[!TIP]

I know this library is quite simple and serves a specific purpose, so one of its API design principles is to minimize the cognitive load for users. You just need to remember to start with an expect<>() call and end with some property access. Leave the rest to editor suggestions and inline documentation.

Install & Import

npm i -D lay-sing
import { expect } from 'lay-sing'

From NPM

deno add npm:lay-sing
import { expect } from 'lay-sing'

From JSR

This library is also published to JSR (@leawind/lay-sing)

deno add @leawind/lay-sing
import { expect } from '@leawind/lay-sing'

From Latest commit

import { expect } from 'https://raw.githubusercontent.com/Leawind/lay-sing/refs/heads/main/src/main/index.ts'
import { Exact } from 'https://raw.githubusercontent.com/Leawind/lay-sing/refs/heads/main/src/utils/index.ts'

Usage

import { expect } from 'lay-sing'

The main module provides utilities for compile-time type validation. These utilities have no runtime impact — they always return a special NOOP value that safely supports almost any property access or method call.

A typical type test statement follows this pattern:

expect<ActualType>().to.be<ExpectedType>().pass
  • It starts with a function call like expect<T>() or compare<T, U>()
  • It ends with a property like .pass or .fail
  • Type error occurs only if the assertion fails

[!CAUTION]

Only statements ending with property access are type assertions. Without property access, type error may never occur:

- expect<true>().to.be<false>()         // Type error never occur
+ expect<true>().to.be<false>().pass // Type Error: Property 'pass' does not exist on type '{ fail: void; }'.

At runtime, the function always returns the NOOP object, which performs no operation. It can be accessed, called, or chained indefinitely without throwing errors.

Common Usage

// Passes only if A and B are identical
expect<keyof { a: 2 }>().to.be<'a'>().pass

// Passes if A extends B
expect<12138>().to.extend<number>().pass

// Passes if mutually assignable
expect<{ a: 1; b: 2 }>().to.equal<{ a: 1 } & { b: 2 }>().pass

// Test property existence
expect<{ name: string }>().to.haveKey<'name'>().pass

Aliases:

expect<never>().to.be<never>().pass
expect<never>().to.be.never

expect<'hello'>().to.extend<string>().pass
expect<'hello'>().to.extend.string

NOOP

A Proxy-based no-op object with the following behavior:

  • Most property/method accesses return the NOOP object itself.
  • .toString(), .valueOf() returns string "[NOOP]".
  • Not thenable (then is undefined).

It's used as returned value of expect() and compare().

expect().foo.bar().baz.qux // Safe, returns NOOP
String(NOOP) // "[NOOP]"
await NOOP // Does not await (not thenable)

Type Tools

It provides some utility types organized into categories for common type-level programming tasks. These can be imported from the lay-sing/utils entry point.

import type { Exact, Extends, Overlap } from 'lay-sing/utils'

Examples

// Import the utility types
import type { ConcatTuple, Exact, If, KeysOfBaseType } from '@leawind/lay-sing/utils'

// Test if exactly the same
type False = Exact<{ a: 1 }, { a?: 1 }> // false
type Yes = Exact<boolean, true | false, 'yes', 'no'> // 'yes'

// Conditional Types
type Result = If<true, 'yes', 'no'> // 'yes'

type FailResult = If<Exact<number, string>, 'yes', 'no'> // 'no'

// Tuple Manipulation
type Combined = ConcatTuple<[1, 2], [3, 4]> // [1, 2, 3, 4]

type UniqueCombined = ConcatUniqueTuple<[1, 2], [2, 3]> // [1, 2, 3]