window.stx.useEventListener is declared with a leading target parameter that the implementation does not have. Calling it the way it actually works is a type error; calling it the way it is typed attaches no listener.
The two disagree
Implementation — packages/stx/src/signals.ts:5566, and this is the function put on the registry at 6284, which becomes window.stx at 6226:
function useEventListener(event, handler, options) {
var target = (options && options.target) || window;
if (typeof target === 'string') target = document.querySelector(target);
if (!target) return;
...
}Event first. The target is optional and travels in options.target.
Declaration — dist/stx.d.ts:274:
declare function useEventListener<K extends keyof WindowEventMap>(
_target: Window | Document | HTMLElement | string | null,
_event: K,
_handler: (event: WindowEventMap[K]) => void,
_options?: boolean | AddEventListenerOptions,
): StxCleanupTarget first.
Why it is worse than a wrong signature
_target accepts string, so the correct two-argument call type-checks as far as the first parameter — 'keydown' is read as a selector — and then fails on the second, where the handler lands in an _event: K slot:
window.stx?.useEventListener('keydown', (event: KeyboardEvent) => { ... })
// No overload matches this call. (TS2769)An author who trusts the type and adds the target gets code that runs and silently does nothing, because useEventListener(window, 'keydown', fn) binds event window, handler 'keydown'.
Found in a real app whose keyboard-shortcut block calls the two-argument form. That code is correct and works; it is the checker that objects.
The standalone export is right
dist/browser-composables.d.ts:38 declares the same name correctly:
export declare function useEventListener<K extends keyof WindowEventMap>(event: K, handler: (e: WindowEventMap[K]) => void, options?: AddEventListenerOptions): () => voidSo the package ships two declarations of one name with different arities, and the registry got the one that does not match the runtime. Same shape as the reactive split — one name, two conventions, and the call site cannot tell which it has.
Fix
Type the registry entry from the implementation: (event, handler, options?) with the target carried on options.target. Aliasing the registry member to the browser-composables declaration would keep them from drifting again.