Skip to content

Instantly share code, notes, and snippets.

@danielres
Last active October 5, 2023 10:34
Show Gist options
  • Save danielres/4f6648df62344504c0f3297655878897 to your computer and use it in GitHub Desktop.
Save danielres/4f6648df62344504c0f3297655878897 to your computer and use it in GitHub Desktop.
A minimal signals implementation in typescript. This is a toy example to help me wrap my head around the pattern.
export type Signal<T> = ReturnType<typeof createSignal<T>>
export function createSignal<Value>(initialValue: Value): {
subscribe: (listener: (v: Value) => void) => () => void
val: Value
} {
let value = initialValue
const listeners: ((v: Value) => void)[] = []
function subscribe(listener: (v: Value) => void) {
listeners.push(listener)
return () => {
const index = listeners.indexOf(listener)
if (index > -1) {
listeners.splice(index, 1)
}
}
}
function update(newValue: Value) {
if (value === newValue) return
value = newValue
listeners.forEach((listener) => listener(newValue))
}
return {
subscribe,
get val() {
return value
},
set val(newValue: Value) {
update(newValue)
},
}
}
export function createComputed<T>(signals: Signal<T>[], fn: () => void) {
const computed = createSignal(fn())
signals.forEach((signal: Signal<T>) =>
signal.subscribe(() => {
computed.val = fn()
})
)
return computed
}
import { createComputed, createSignal } from './signals'
const num1 = createSignal(2)
const num2 = createSignal(3)
const sum = createComputed([num1, num2], () => num1.val + num2.val)
num1.val = 4
num2.val = 5
sum.subscribe(value => {
document.getElementById('sum-value').textContent = value;
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment