Skip to content

Commit 04b6935

Browse files
committed
feat: adds size method
1 parent 65fc385 commit 04b6935

File tree

3 files changed

+58
-9
lines changed

3 files changed

+58
-9
lines changed

src/rv.spec.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,37 @@ describe('rv function', () => {
9090

9191
expect(val()).toBe(30)
9292
})
93+
94+
describe('size method', () => {
95+
it('returns 0 if there is no listeners', () => {
96+
const counter = rv(33)
97+
expect(counter.size()).toBe(0)
98+
})
99+
100+
it('returns number of listeners', () => {
101+
const counter = rv(33)
102+
counter.on(() => {})
103+
counter.on(() => {})
104+
expect(counter.size()).toBe(2)
105+
})
106+
107+
it('correctly recognizes unsubscribes', () => {
108+
const counter = rv(33)
109+
110+
const unsub1 = counter.on(() => {})
111+
const unsub2 = counter.on(() => {})
112+
113+
expect(counter.size()).toBe(2)
114+
115+
unsub1()
116+
expect(counter.size()).toBe(1)
117+
118+
unsub1()
119+
// still one, because we've already unsubscribed from this function
120+
expect(counter.size()).toBe(1)
121+
122+
unsub2()
123+
expect(counter.size()).toBe(0)
124+
})
125+
})
93126
})

src/rv.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const defaultEq = <T>(oldValue: T, newValue: T): boolean => oldValue === newValu
88
* @template T The type of the stored value.
99
*
1010
* @param val The initial value of the reactive variable.
11-
* @param options Optional configuration for the reactive variable.
11+
* @param opts Optional configuration for the reactive variable.
1212
*
1313
* @returns A reactive variable function that allows getting, setting, and listening for updates.
1414
*
@@ -53,22 +53,22 @@ const defaultEq = <T>(oldValue: T, newValue: T): boolean => oldValue === newValu
5353
* positiveVar(5) // there will be no logs
5454
* ```
5555
*/
56-
export function rv<T>(val: T, options?: RvInitOptions<T>): Rv<T> {
57-
const { eq = defaultEq, on } = options ?? <RvInitOptions<T>>{}
56+
export function rv<T>(val: T, opts?: RvInitOptions<T>): Rv<T> {
57+
const { eq = defaultEq, on } = opts ?? <RvInitOptions<T>>{}
5858

5959
const listeners = new Set<Listener<T>>()
6060

6161
if (on) listeners.add(on)
6262

63-
const fn: Rv<T> = (...args: [] | [newValue: T, options?: RvOptions<T>]): T => {
63+
const fn: Rv<T> = (...args: [] | [newValue: T, opts?: RvOptions<T>]): T => {
6464
if (args.length === 0) return val
6565

66-
const [newValue, options] = args
66+
const [newValue, opts] = args
6767

6868
let eqfn: EqualFn<T> = eq
6969

70-
if (typeof options?.eq !== 'undefined') {
71-
eqfn = options.eq === false ? defaultEq : options.eq
70+
if (typeof opts?.eq !== 'undefined') {
71+
eqfn = opts.eq === false ? defaultEq : opts.eq
7272
}
7373

7474
if (eqfn(val, newValue)) return val
@@ -81,6 +81,9 @@ export function rv<T>(val: T, options?: RvInitOptions<T>): Rv<T> {
8181
return val
8282
}
8383

84+
fn.off = (f): void => void listeners.delete(f)
85+
fn.size = (): number => listeners.size
86+
8487
fn.on = (listener): CleanupFn => {
8588
listeners.add(listener)
8689

@@ -97,6 +100,7 @@ export function rv<T>(val: T, options?: RvInitOptions<T>): Rv<T> {
97100
* The function is immediately executed to determine the initial value.
98101
*
99102
* @template T The type of the stored value.
103+
*
100104
* @param init A function that returns the initial value.
101105
* @param options Optional configuration for equality comparison and event listeners.
102106
*

src/types.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,19 @@ export interface Rv<T> {
6666
*
6767
* @returns A cleanup function to remove the listener.
6868
*/
69-
on(listener: Listener<T>): CleanupFn
69+
on: (listener: Listener<T>) => CleanupFn
70+
/**
71+
* Unsubscribes a listener from value changes.
72+
*
73+
* @param listener A callback function that is needed to be unsubscribed.
74+
*/
75+
off: (listener: Listener<T>) => void
76+
/**
77+
* Returns the number of listeners for this reactive variable.
78+
*
79+
* @returns listener count.
80+
*/
81+
size: () => number
7082
}
7183

7284
/**
@@ -113,5 +125,5 @@ export interface RvInit {
113125
*
114126
* @returns A reactive variable function.
115127
*/
116-
fn<T>(init: () => T, options?: RvInitOptions<T>): Rv<T>
128+
fn: <T>(init: () => T, options?: RvInitOptions<T>) => Rv<T>
117129
}

0 commit comments

Comments
 (0)