Skip to content

feat(agera,intl,kida,nanoviews,query,router,svelte-kit): rename ValueOrAccessor to Signalish - #210

Merged
dangreen merged 1 commit into
mainfrom
feat/signalish-rename
Aug 24, 2026
Merged

feat(agera,intl,kida,nanoviews,query,router,svelte-kit): rename ValueOrAccessor to Signalish#210
dangreen merged 1 commit into
mainfrom
feat/signalish-rename

Conversation

@dangreen

Copy link
Copy Markdown
Member
interface ButtonProps {
  title: ValueOrAccessor<string>
  size?: ValueOrAccessor<'s' | 'm' | 'l'>
  onSelect: (event: Event) => void
  id?: string
}

ValueOrAccessor is the type a consumer of this library writes most: 705 occurrences in this repo, 577 of them in dom/attributes.ts alone. It is fifteen characters of noun-conjunction-noun, and no other library spells it that way.

interface ButtonProps {
  title: Signalish<string>
  size?: Signalish<'s' | 'm' | 'l'>
  onSelect: (event: Event) => void
  id?: string
}

Where the name comes from

Only three ecosystems publish a "plain value or reactive thing" union at all, and all three name it as a modifier on a noun rather than a conjunction:

name where it is used
Preact Signalish<T> = T | SignalLike<T> (preact/src/dom.d.ts) 1088 times in jsx.d.ts — the DOM attribute types, the same position as ours
solid-primitives MaybeAccessor<T> = T | Accessor<T> headless primitives
Vue MaybeRef<T>, MaybeRefOrGetter<T> composable signatures

Angular, Svelte, nanostores, MobX, RxJS, Jotai, Zustand and Recoil ship no such union — their props are either plain or always wrapped.

Signalish is the shortest of the three, and it comes from the library whose usage matches ours exactly. The union is written over Accessor, but ReadableSignal<T> extends Accessor<T>, so from the writing side there is no difference to see: a signal, an accessor, or a plain value all fit, and a signal is what gets passed most.

What else moves with it

  • MaybeAccessorValueSignalishValue, so the extractor keeps the name of the union it extracts from. (Preact pairs Signalish with UnpackSignal; a noun reads better here than a verb.)
  • AnyValueOrAccessorAnySignalish.
  • query's SignalsParamsSignalishParams — it maps every element of a parameter tuple through this union, so it promised signals while accepting plain values too.
  • Parameters that spelled the old name — valueOrAccessor, valueOrReadable — are now source.

Nothing breaks

Every old name stays as a deprecated alias, marked for removal:

/**
 * @deprecated Use `Signalish`
 * @todo Drop at the next major
 */
export type ValueOrAccessor<T> = Signalish<T>

ValueOrSignal and ValueOrWritableSignal are aliased too. They have no consumer left in this repo and were on the way out, but dropping a published export is the break this PR is avoiding.

Types cost nothing at runtime: every bundle in the chain is byte-identical and no size pin moves.

Checked

All eleven packages: lint, tsc --noEmit, and unit suites — agera 155, kida 64, store 57, nanoviews 114, query 163, router 129, intl 114, preact 9, react 15, svelte 4, svelte-kit 21.

The narrowing types TruthyValueOrSignal/FalsyValueOrSignal in nanoviews belong to the same family and follow in a separate PR; they are left untouched here so this one stays mechanical.

@codecov

codecov Bot commented Aug 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 85.33%. Comparing base (47f794b) to head (7507eb4).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #210   +/-   ##
=======================================
  Coverage   85.33%   85.33%           
=======================================
  Files         139      139           
  Lines        3143     3143           
  Branches      591      591           
=======================================
  Hits         2682     2682           
  Misses        332      332           
  Partials      129      129           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…eOrAccessor` to `Signalish`

`ValueOrAccessor` is the most repeated type a consumer writes - 705 occurrences in this repo alone, 577 of them in the DOM attribute types - and no neighbouring library spells it that way. Preact names the same union `Signalish` and uses it in the same position, its JSX attribute types; solid-primitives publishes `MaybeAccessor` for the identical shape; Vue has `MaybeRef`. `Signalish` is the shortest of the three and reads as the thing consumers actually pass: a signal, an accessor over one, or a plain value.

`MaybeAccessorValue` becomes `SignalishValue` so the extractor keeps its union's name, `AnyValueOrAccessor` becomes `AnySignalish`, and `query`'s `SignalsParams`, which maps each parameter through this union, becomes `SignalishParams`. The parameters that carried the old name in their spelling are now `source`.

The old names stay as deprecated aliases, so nothing breaks; they are marked to drop at the next major.
@dangreen
dangreen force-pushed the feat/signalish-rename branch from c6c4521 to 7507eb4 Compare August 24, 2026 16:18
@dangreen
dangreen merged commit c42723a into main Aug 24, 2026
10 checks passed
@dangreen
dangreen deleted the feat/signalish-rename branch August 24, 2026 16:23
@github-actions github-actions Bot mentioned this pull request Aug 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant