import { createAtom, toObserver } from './atom' import type { Atom, Observer, Subscription } from './types' export class Store { private atom: Atom constructor(getValue: (prev?: NoInfer) => T) constructor(initialValue: T) constructor(valueOrFn: T | ((prev?: T) => T)) { // createAtom has overloads that return ReadonlyAtom for functions and Atom for values // Store always needs Atom for setState, so we assert the return type this.atom = createAtom( valueOrFn as T | ((prev?: NoInfer) => T), ) as Atom } public setState(updater: (prev: T) => T) { this.atom.set(updater) } public get state() { return this.atom.get() } public get() { return this.state } public subscribe( observerOrFn: Observer | ((value: T) => void), ): Subscription { return this.atom.subscribe(toObserver(observerOrFn)) } } export class ReadonlyStore implements Omit, 'setState'> { private atom: Atom constructor(getValue: (prev?: NoInfer) => T) constructor(initialValue: T) constructor(valueOrFn: T | ((prev?: T) => T)) { // createAtom has overloads that return ReadonlyAtom for functions and Atom for values // Store always needs Atom for setState, so we assert the return type this.atom = createAtom( valueOrFn as T | ((prev?: NoInfer) => T), ) as Atom } public get state() { return this.atom.get() } public get() { return this.state } public subscribe( observerOrFn: Observer | ((value: T) => void), ): Subscription { return this.atom.subscribe(toObserver(observerOrFn)) } } export function createStore( getValue: (prev?: NoInfer) => T, ): ReadonlyStore export function createStore(initialValue: T): Store export function createStore( valueOrFn: T | ((prev?: T) => T), ): Store | ReadonlyStore { if (typeof valueOrFn === 'function') { return new ReadonlyStore(valueOrFn as (prev?: NoInfer) => T) } return new Store(valueOrFn) }