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

@aurelienbbn/oxlint-plugin-type-evidence

v0.1.1

Published

Strict oxlint rules preserving TypeScript type evidence at contracts and boundaries.

Readme

@aurelienbbn/oxlint-plugin-type-evidence

npm downloads CI license node

10 oxlint rules that stop TypeScript from losing what it knows: no laundering casts, no unknown leaking past boundaries, no widening a value you just wrote.

pnpm add -D @aurelienbbn/oxlint-plugin-type-evidence oxlint   # oxlint >=1.82.0 <2.0.0
// oxlint.config.ts
import { strictRules } from "@aurelienbbn/oxlint-plugin-type-evidence";
import { defineConfig } from "oxlint";

export default defineConfig({
  jsPlugins: ["@aurelienbbn/oxlint-plugin-type-evidence"],
  rules: { ...strictRules }, // all 10 at "error"
});

Exports: default (the plugin, type-evidence/*), strictRules (every rule at "error").

Report-only, 0 autofix: restoring evidence (named contract, parser, inference) is a choice no tool makes.

❌ vs ✅

| Rule | ❌ Fires | ✅ Passes | | ------------------------------------------- | ------------------------------------------------------------- | ---------------------------------------------------- | | no-chained-type-assertions | input as unknown as User | [1, 2] as const (all-as const chains) | | no-object-parameters | function handle(payload: object) | function handle<T extends object>(payload: T) | | no-unknown-parameters | function parse(value: unknown) | function isUser(value: unknown): value is User | | no-unknown-returns | async function load(): Promise<unknown> | function load() { return compute(); } | | no-unknown-type-aliases | type Data = unknown | type Payload = Box<unknown> | | no-unsafe-dictionary-type | type Dict = Record<string, unknown> | type Events = Record<string, { payload: unknown }> | | no-known-value-widening | const state: unknown = { status: "idle" } | const acc: Record<string, number> = {} | | no-widen-then-assert | const data: unknown = { id: 1 }; const user = data as User; | assert a precisely typed binding | | require-safety-comment-for-type-assertion | const user = input as User; | // SAFETY: input validated upstream above it | | no-runtime-typeof | const kind = typeof value | typeof window !== "undefined" |

| Rule | Also fires on | Stays valid | | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------- | | no-chained-type-assertions | any chain of ≥ 2 assertions: it launders through unknown / any | chains made only of as const | | no-object-parameters | object reached through a same-file alias or a union member | generic constraints (T extends object) | | no-unknown-parameters | — | a parameter named cause; the subject of a type predicate (value is T / asserts value) | | no-unknown-returns | unknown directly, in a union, in Promise<unknown> / PromiseLike<unknown>, via a same-file alias | omitted annotation; unknown nested in a named object shape ({ cause: unknown }) | | no-unknown-type-aliases | unknown through parens, a union, or transitive same-file aliases | unknown nested in a generic argument | | no-unsafe-dictionary-type | broad keys (string, number, symbol, PropertyKey, or unions containing one) × contract-free values (unknown, any, object, {}), as Record, index signature, or mapped type | finite-key records, exhaustive mapped types, nested unknown inside a value shape, Map / WeakMap, type-parameter constraints | | no-known-value-widening | a literal, object, array, function, class, new, or template flowing into unknown, object, broad Record, an index-signature literal, or an anonymous type literal | the empty-object accumulator const acc: Record<string, number> = {}. ⚠️ {} into unknown / object still reports | | no-widen-then-assert | a const declared broad over a known initializer, re-narrowed later in the same function with an assertion | reassigned let bindings | | require-safety-comment-for-type-assertion | every assertion except as const without a marker on or before its owning statement | — | | no-runtime-typeof | typeof anywhere else: it rebuilds type evidence at runtime and only reaches primitive buckets | existence probes; with allowInTypeGuards: any function returning a type predicate, and typeof on the function's own unknown parameter |

| Rule | Option | Default | | ------------------------------------------- | ------------------- | -------------------------------------------------------------------- | | require-safety-comment-for-type-assertion | markers | ["SAFETY"] (replaced, not merged) | | no-runtime-typeof | allowInTypeGuards | true (unlike the source concept); false deliberately tightens it |

A safety comment needs ≥ 3 real words, not a placeholder (todo, fixme, trust me, this is safe); trailing same-line comments and empty markers don't count. It never proves the cast safe: the invariant still needs human review.

Boundaries are exempt

**/boundaries/**   **/decoders/**   **/adapters/**   *.boundary.{ts,tsx,js,jsx,mts,cts,mjs,cjs}
        ▲
        └── unknown input is legitimate here: no-unknown-parameters, no-unknown-returns,
            no-unknown-type-aliases, no-unsafe-dictionary-type, no-runtime-typeof stay silent

Single-file and syntactic

No type checker, no cross-file resolution.

| Limit | Detail | | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | alias resolution | same-file, non-generic aliases only | | binding tracking | no-known-value-widening and no-widen-then-assert resolve bindings through lexical scope: captured bindings are tracked across function boundaries, shadowed bindings stay separate | | alias consumers | no-unsafe-dictionary-type reports an unsafe alias at its declaration; its consumers aren't re-reported | | overloads | TSDeclareFunction overload signatures aren't visited by the parameter/return rules | | policy, not proof | populated structural contracts aren't automatically evidence loss. Preferring internal discriminated unions over typeof is architecture policy, not proof typeof is unsafe | | recursion | recursive type traversal terminates normally |

Credit: all 10 rules re-implement concepts from dmmulroy/anti-slop (Dillon Mulroy, MIT) in this repo's own style; no code copied.

Registered contract inventory

Generated from package exports by pnpm catalog. Rule-specific options and limitations are described above and in the source tests.

| Rule/check | Trigger or review scope | | ------------------------------------------- | ---------------------------------------------------------------------------------------- | | no-chained-type-assertions | Disallow chains of type assertions that launder a value through unknown or any. | | no-known-value-widening | Disallow flowing syntactically known values into explicitly broad type annotations. | | no-object-parameters | Disallow parameter annotations that resolve to the shapeless object keyword. | | no-runtime-typeof | Disallow runtime typeof checks outside existence probes and type guard functions. | | no-unknown-parameters | Disallow unknown in parameter annotations outside type guards and error causes. | | no-unknown-returns | Disallow unknown in return type annotations, including inside Promise results. | | no-unknown-type-aliases | Disallow type aliases that resolve to unknown. | | no-unsafe-dictionary-type | Disallow dictionary types whose broad keys map to contract-free values. | | no-widen-then-assert | Disallow widening a known const initializer and re-narrowing it later with an assertion. | | require-safety-comment-for-type-assertion | Require every non-const type assertion to carry a marker comment justifying its safety. |

Credited concepts

  • anti-slop by Dillon Mulroy (MIT, concept re-implemented)