no-floating-geolocation-watches
Require geolocation watch IDs to be retained so they can be cleared.
Rule catalog ID: R014
Targeted pattern scopeโ
This rule targets browser geolocation watcher registration:
navigator.geolocation.watchPosition(...)window.navigator.geolocation.watchPosition(...)globalThis.navigator.geolocation.watchPosition(...)
The rule reports calls whose returned watch ID is immediately discarded. The
watch ID is the handle needed to unregister the watcher with
navigator.geolocation.clearWatch(...).
What this rule reportsโ
The rule reports:
- standalone watcher registration such as
navigator.geolocation.watchPosition(onPosition); - voided watcher registration such as
void navigator.geolocation.watchPosition(onPosition); - TypeScript-wrapped expressions that still discard the returned watch ID
It intentionally does not require same-function clearWatch() calls. Ownership
can be transferred to a component instance, route lifecycle, returned value, or
watch manager.
Why this rule existsโ
watchPosition() installs repeated location monitoring callbacks. The browser
returns a numeric ID for that watch, and clearWatch(id) uses that ID to remove
the registered monitoring handlers. If the ID is discarded, the code that owns
the lifecycle cannot reliably unregister the watcher.
Incorrectโ
navigator.geolocation.watchPosition(onPosition);
void navigator.geolocation.watchPosition(onPosition, onError);
Correctโ
const watchId = navigator.geolocation.watchPosition(onPosition);
navigator.geolocation.clearWatch(watchId);
return navigator.geolocation.watchPosition(onPosition);
registerWatch(navigator.geolocation.watchPosition(onPosition));
Behavior and migration notesโ
Store the returned watch ID in the owner that will call clearWatch(). In UI
code, that is usually the component, route, or view lifecycle. In shared
libraries, returning the ID or passing it to a watcher manager keeps ownership
explicit.
This rule does not autofix. Choosing the owner and cleanup point is a semantic decision.
ESLint flat config exampleโ
import runtimeCleanup from "eslint-plugin-runtime-cleanup";
export default [
runtimeCleanup.configs.recommended,
];
When not to use itโ
Do not enable this rule for code that intentionally creates page-lifetime geolocation watches and does not need explicit teardown. Prefer a narrow disable comment with a reason in those files.