preactjs / signals

Manage state with style in every framework
https://preactjs.com/blog/introducing-signals/
MIT License
3.81k stars 95 forks source link

How should one check for `compSig instanceof Signal` for a computed after #587? #613

Closed AlexJeffcott closed 1 month ago

AlexJeffcott commented 1 month ago

I would like to check to see whether a variable is a computed. I previously did this using instanceof Signal which was good enough for my purposes.

Since upgrading preact/signals this no longer works as ReadonlySignal no longer extends Signal.

This is the change in question.

This is the sort of code I wrote.

getValue(computedOrValue: ReadonlySignal<V> | V): N {
  if (computedOrValue instanceof Signal) { \\ checks is a Signal/Computed
    return computedOrValue.value
  } else {
    return computedOrValue
  }
}

This is the sort of code I would like to be able to write.

getValue(computedOrValue: ReadonlySignal<V> | V): N {
  if (computedOrValue instanceof ReadonlySignal) { \\ can check is a Computed
    return computedOrValue.value
  } else {
    return computedOrValue
  }
}
XantreDev commented 1 month ago

I think you could do it like this

const Computed = computed(() => null).prototype

if (a instanceof Computed) {}

More future proof solution

if (a?.brand === Symbol.for("preact-signals")) {} // true for any Signal and ReadonlySignal
XantreDev commented 1 month ago

But actually under the hood ReadonlySignal still extends Signal and if you check it instanceof Signal it will return true with ReadonlySignal

JoviDeCroock commented 1 month ago

Exactly this change is only on a types level and does not affect any runtime, the type narrowing is just a bit broken in TypeScript it feels like.