You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Replace the current magic-string error messages ([TIMEOUT], [ABORT], [EVENTS]) with dedicated Error subclasses. Consumers would use instanceof checks instead of fragile string matching.
Current state
// Library throwsnewError('[TIMEOUT]: Element #foo cannot be found after 500ms')newError('[ABORT]: Observation replaced by a new wait() call')newError('[EVENTS]: events array cannot be empty')// Consumer must checkcatch(e){if((easError).message.includes('[TIMEOUT]')){ ... }}
Problems:
String matching is fragile: any message wording change is a silent breaking change
No TypeScript type narrowing from instanceof checks
Inconsistency: abort paths throw DOMException with name: 'AbortError' while timeout/events paths throw plain Error
Proposed API
// New exportsexportclassTimeoutErrorextendsError{readonlytarget: DOMTargetreadonlytimeout: numberconstructor(target: DOMTarget,timeout: number){super(`Element "${target}" not found after ${timeout}ms`)this.name='TimeoutError'this.target=targetthis.timeout=timeout}}exportclassObservationAbortedErrorextendsError{constructor(reason?: string){super(reason??'Observation replaced by a newer call')this.name='ObservationAbortedError'}}exportclassInvalidEventsErrorextendsError{constructor(){super('events array cannot be empty')this.name='InvalidEventsError'}}
Consumer code:
import{DOMObserver,TimeoutError}from'@untemps/dom-observer'try{awaitobs.wait('#foo',{timeout: 500})}catch(e){if(einstanceofTimeoutError){console.log(`Timed out waiting for ${e.target} after ${e.timeout}ms`)}if(einstanceofDOMException&&e.name==='AbortError'){// AbortSignal path — already uses DOMException, unchanged}}
Breaking changes
Any consumer code that matches on .message.includes('[TIMEOUT]') etc. will need to migrate to instanceof checks.
The internal [TIMEOUT] prefix is removed from messages — if anything logs error messages, the format changes.
Migration guide
Before
After
e.message.includes('[TIMEOUT]')
e instanceof TimeoutError
e.message.includes('[ABORT]')
e instanceof ObservationAbortedError
e.message.includes('[EVENTS]')
e instanceof InvalidEventsError
Notes
The AbortSignal rejection path already uses DOMException (correct) and is unchanged.
TimeoutError storing target and timeout as structured properties allows callers to inspect the error programmatically without parsing a message string.
See the non-breaking stepping stone in issue feat: export error message constants #41 (export error constants) — that issue can be delivered first to help consumers migrate.
Summary
Replace the current magic-string error messages (
[TIMEOUT],[ABORT],[EVENTS]) with dedicatedErrorsubclasses. Consumers would useinstanceofchecks instead of fragile string matching.Current state
Problems:
instanceofchecksDOMExceptionwithname: 'AbortError'while timeout/events paths throw plainErrorProposed API
Consumer code:
Breaking changes
.message.includes('[TIMEOUT]')etc. will need to migrate toinstanceofchecks.[TIMEOUT]prefix is removed from messages — if anything logs error messages, the format changes.Migration guide
e.message.includes('[TIMEOUT]')e instanceof TimeoutErrore.message.includes('[ABORT]')e instanceof ObservationAbortedErrore.message.includes('[EVENTS]')e instanceof InvalidEventsErrorNotes
AbortSignalrejection path already usesDOMException(correct) and is unchanged.TimeoutErrorstoringtargetandtimeoutas structured properties allows callers to inspect the error programmatically without parsing a message string.