implement
Introduction

Introduction

Framework-aware lint rules for implement apps — leaked subscriptions, broken ARIA, and Lifecycle that could be Effect.

TypeScript catches a lot in an implement app, because there is no template language for it to lose sight of — a component is a function call and its props are an object literal. But some mistakes are the right shape and still wrong. aria-lable is a perfectly good key on a props object. A subscribe whose unsubscribe you drop on the floor type-checks exactly like one you keep.

@implementjs/eslint is a small set of rules for those. It is written against ESLint's plugin API, and it runs under either linter — ESLint, or oxlint through oxlint's ESLint-compatible plugin support. One package, one set of rules, whichever linter you already have.

Set it up in a few lines of config, and read how the rules see your code for what they can and cannot tell you.

The rules

Six of them are about implement itself — signals that get read wrong, subscriptions that outlive their owner, markup that renders once when it meant to stay live:

RuleRecommendedCatches
no-hanging-unsubscribeerrora subscription to a longer-lived signal whose unsubscribe is discarded
prefer-effectwarnan ImplementLifecycle that exists only to own a watch
no-signal-conditionerrora signal tested for truth, which is always true
no-signal-collectionwarna Set or Map inside a signal() rather than a reactive collection
prefer-foreacherror.get().map() rendering a list that will never update
no-htmlerrorevery use of Html, which does not sanitize

The other five check the accessibility props you write by hand, against the WAI-ARIA 1.2 vocabulary:

RuleRecommendedCatches
valid-ariaerrora misspelled aria-* key, or a value the attribute does not permit
valid-roleerrora misspelled or abstract role
role-has-required-aria-propserrora role missing the property it is incomplete without
role-supports-aria-propserroran aria-* property the role ignores
no-redundant-roleswarna role an element already has