anti-slop turns low-evidence TypeScript into a lint failure instead of a style argument

updates

dmmulroy/anti-slop is interesting because it uses Oxlint to reject TypeScript and JavaScript patterns that fabricate certainty, hide weak contracts, or quietly throw away evidence the compiler already had.

GitHub README capture for dmmulroy/anti-slop

A lot of linting still lives in the world of style bikeshedding.

Teams argue about semicolons, import order, quote marks, or whether a formatter should wrap one more line. Those decisions matter a little, but they rarely touch the harder problem in TypeScript codebases: how easily developers can pretend they know more than the code actually proves.

That is why anti-slop from dmmulroy/anti-slop stands out.

The repo is not trying to be a universal best-practices bundle. Its thesis is much narrower and much sharper. It uses Oxlint rules to reject what the author calls low-evidence and low-signal TypeScript and JavaScript patterns: code that widens known values, hides uncertainty behind broad types, or asserts facts back into existence after losing them.

That is a more interesting target than style consistency because it goes after a real failure mode in modern AI-assisted codebases. A formatter cannot tell you when a code path has started bluffing. A rule set like this can at least make the bluff much harder to merge.

The best idea here is that type safety is treated as evidence, not decoration

The rule list in the README tells the story quickly.

anti-slop rejects chained assertions, unknown-heavy contracts, unsafe dictionary types, broad object parameters, Reflect.get, Reflect.apply, and local flows where developers widen a known value and then assert it back later. One rule even requires a specific safety comment before a non-const type assertion.

That sounds strict because it is strict.

But there is a coherent philosophy underneath it. The repo keeps asking the same question: what does the program actually know here, and what are you smuggling in by hand?

That framing is useful. A lot of TypeScript debt does not start with an obvious any. It starts when code throws away a precise shape, replaces it with something broad, and then reintroduces certainty with an assertion or a loose container type. The compiler still looks happy. The runtime guarantees did not actually improve.

anti-slop tries to make those moves visible.

It is opinionated in the right place

One of the strongest product choices in this repo is not a lint rule. It is the distribution model.

The README explicitly says the project is meant to be vendored instead of installed as a fixed npm dependency. That is a smart stance for something this opinionated. These rules are closer to organizational policy than to a normal library API.

By telling teams to copy the source, read it, and adapt it, the repo avoids two bad outcomes at once.

First, it does not pretend one author's taste should become an untouchable external dependency inside every codebase. Second, it lowers the friction for teams that agree with the core thesis but want to soften or tighten specific rules.

That is exactly how this kind of tooling should be framed. Lint rules that encode engineering values work best when teams can own them. anti-slop seems to understand that.

The bundled install skill reinforces the same idea. The repo is not only shipping rules. It is shipping a path for agent-driven setup, which makes sense in a world where more codebases are being maintained with coding assistants in the loop.

The rules push teams toward stronger boundaries

The most valuable part of the rule set is that it does not only say "be stricter." It nudges developers toward better boundary design.

For example, rejecting ad hoc typeof narrowing in favor of boundary parsing is more than a syntactic preference. It encourages teams to centralize validation rather than scattering tiny local checks around the codebase.

Rejecting unknown parameters and unknown return types forces more intentional contracts.

Rejecting broad dictionary types and object inputs makes it harder to hide unmodeled data under containers that say almost nothing.

Rejecting module mocks points in the same direction from a testing angle. The rule prefers real dependency seams over magic replacement. Whether every team will want that rule is debatable, but the design pressure is understandable: if the seams are explicit, the system is easier to reason about.

Taken together, these rules push code toward a cleaner posture. Parse at the edges. Preserve the specific knowledge you already have. Do not widen contracts unless you absolutely mean it. Do not use assertions as a substitute for proof.

That is a serious set of defaults.

This is especially relevant in the AI coding era

The repo also feels timely.

AI coding tools are very good at producing superficially tidy code that still carries weak contracts. They often reach for unknown, broad records, loose wrappers, or type assertions to bridge gaps quickly. The result can look disciplined while quietly making the program less trustworthy.

That is where anti-slop has a real angle.

It does not claim to solve all generated-code quality problems. What it can do is encode a set of structural refusals. The agent or developer can still write the feature, but certain shortcuts now become impossible to treat as harmless cleanup later.

I think that matters. As more teams adopt agent-assisted workflows, the bottleneck shifts from raw code generation to policy enforcement. The winning tools will not just help create code faster. They will make it harder to ship code that says more than it can prove.

anti-slop is a small but concrete example of that shift.

Where teams should stay realistic

This repo is not for everyone, and that is part of why it is worth paying attention to.

Some rules will feel too rigid for legacy codebases, fast prototypes, or teams with very different ergonomics around testing and type assertions. If your codebase leans heavily on dynamic boundaries, progressive migration, or broad integration surfaces, enabling every rule at once could be noisy.

The repo largely anticipates that objection by encouraging vendoring and customization. That keeps the tool honest. It is presenting a philosophy, not masquerading as neutral infrastructure.

There is also a social question here. When a rule set is this opinionated, adoption depends on whether the team shares the worldview behind it. Without that buy-in, the rules can feel like taste masquerading as correctness.

Still, I would rather see a repo make its values explicit than hide them behind generic language about quality.

Why this repo is worth watching

dmmulroy/anti-slop is worth watching because it treats type safety as a question of evidence, not aesthetics.

That sounds simple, but it points at a bigger need in modern software teams. We need more tooling that can distinguish between code that is merely well-formatted and code that keeps its claims grounded in what the system actually knows.

The project is fresh, and its exact rule set will not be universal. But the underlying idea is strong: if a codebase keeps widening, asserting, and hand-waving its way around uncertainty, the problem is not style. The problem is that the software is getting harder to trust.

A lint rule that names that problem clearly is already doing something useful.

Repo

GitHub: https://github.com/dmmulroy/anti-slop