Skip to content

Consider renaming “Signal” to avoid collision with existing AbortSignal #272

@ryanflorence

Description

@ryanflorence

The term "signal" is already a well-established concept in the JavaScript platform via AbortController / AbortSignal. These are deeply integrated into the web platform, widely used, and baked into many APIs (fetch, streams, event targets, etc.).

Introducing another first-class primitive called "Signal"—with unrelated semantics—creates ambiguous vocabulary:

  • Developers will need to clarify "reactive signals" vs "abort signals."
  • Documentation, examples, and teaching will repeatedly have to disambiguate two unrelated concepts with the same name.
  • Frameworks and applications that use both will encounter real ergonomics friction.

Our in-progress Remix 3 component API relies heavily on abort signals (like event-handler/render task re-entry and element/component lifecycle etc.). We also plan to support reactive values. Having both concepts named signal creates unavoidable naming collisions.

This is not a matter of preference but of namespace hygiene: JavaScript already has a Signal, with different meaning and long-term permanence.

Maybe we can consider a different term? Any name that avoids overloading existing platform terminology would improve long-term clarity for the entire ecosystem.


Suggestion: Tracked

  • To avoid collisions with abort signals, Remix intends to use track instead of signal
  • This proposal already uses "track" to describe the feature
  • Ripple.js also uses track, suggesting the term is gaining natural ... traction 😏

It also reads nicely:

let counter = new Tracked.State(0)

Illustrative pseudo-code:

interface TrackedValue<T> {
  read(): T
}

declare namespace Tracked {
  class State<T> implements TrackedValue<T> {
    constructor(initial: T, options?: TrackOptions<T>)
    read(): T
    write(next: T): void
  }

  class Computed<T = unknown> implements TrackedValue<T> {
    constructor(compute: (this: Computed<T>) => T, options?: TrackOptions<T>)
    read(): T
  }

  // ... etc.
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions