@storve/core 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (198) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +993 -26
  3. package/dist/adapters/indexedDB.cjs +0 -1
  4. package/dist/adapters/indexedDB.mjs +0 -1
  5. package/dist/adapters/localStorage.cjs +0 -1
  6. package/dist/adapters/localStorage.mjs +0 -1
  7. package/dist/adapters/memory.cjs +0 -1
  8. package/dist/adapters/memory.mjs +0 -1
  9. package/dist/adapters/sessionStorage.cjs +0 -1
  10. package/dist/adapters/sessionStorage.mjs +0 -1
  11. package/dist/async-entry.d.ts +0 -1
  12. package/dist/async.cjs +0 -1
  13. package/dist/async.d.ts +0 -1
  14. package/dist/async.mjs +0 -1
  15. package/dist/batch.d.ts +0 -1
  16. package/dist/compose.d.ts +0 -1
  17. package/dist/computed-entry.d.ts +0 -1
  18. package/dist/computed.cjs +0 -1
  19. package/dist/computed.d.ts +0 -1
  20. package/dist/computed.mjs +0 -1
  21. package/dist/devtools/history.d.ts +0 -1
  22. package/dist/devtools/index.d.ts +0 -1
  23. package/dist/devtools/redux-bridge.d.ts +0 -1
  24. package/dist/devtools/snapshots.d.ts +0 -1
  25. package/dist/devtools/withDevtools.d.ts +0 -1
  26. package/dist/devtools.cjs +0 -1
  27. package/dist/devtools.mjs +0 -1
  28. package/dist/extensions/noop.d.ts +0 -1
  29. package/dist/index.cjs +0 -1
  30. package/dist/index.d.ts +0 -1
  31. package/dist/index.mjs +0 -1
  32. package/dist/persist/adapters/indexedDB.d.ts +0 -1
  33. package/dist/persist/adapters/localStorage.d.ts +0 -1
  34. package/dist/persist/adapters/memory.d.ts +0 -1
  35. package/dist/persist/adapters/sessionStorage.d.ts +0 -1
  36. package/dist/persist/debounce.d.ts +0 -1
  37. package/dist/persist/hydrate.d.ts +0 -1
  38. package/dist/persist/index.d.ts +0 -1
  39. package/dist/persist/serialize.d.ts +0 -1
  40. package/dist/persist.cjs +0 -1
  41. package/dist/persist.mjs +0 -1
  42. package/dist/proxy.d.ts +0 -1
  43. package/dist/registry-qtr1UpFU.js +0 -1
  44. package/dist/registry-zaKZ1P-s.js +0 -1
  45. package/dist/registry.d.ts +0 -1
  46. package/dist/signals/createSignal.d.ts +0 -1
  47. package/dist/signals/index.d.ts +0 -1
  48. package/dist/signals/useSignal.d.ts +0 -1
  49. package/dist/signals.cjs +0 -1
  50. package/dist/signals.mjs +0 -1
  51. package/dist/store.d.ts +0 -1
  52. package/dist/sync/channel.d.ts +0 -1
  53. package/dist/sync/index.d.ts +0 -1
  54. package/dist/sync/protocol.d.ts +0 -1
  55. package/dist/sync/withSync.d.ts +0 -1
  56. package/dist/sync.cjs +0 -1
  57. package/dist/sync.mjs +0 -1
  58. package/dist/types.d.ts +0 -1
  59. package/package.json +9 -3
  60. package/CHANGELOG.md +0 -151
  61. package/benchmarks/run.ts +0 -102
  62. package/benchmarks/week2.md +0 -9
  63. package/benchmarks/week2.ts +0 -64
  64. package/benchmarks/week4.md +0 -13
  65. package/benchmarks/week4.ts +0 -178
  66. package/benchmarks/week5.md +0 -15
  67. package/benchmarks/week5.ts +0 -184
  68. package/coverage/coverage-summary.json +0 -31
  69. package/dist/adapters/indexedDB.cjs.map +0 -1
  70. package/dist/adapters/indexedDB.mjs.map +0 -1
  71. package/dist/adapters/localStorage.cjs.map +0 -1
  72. package/dist/adapters/localStorage.mjs.map +0 -1
  73. package/dist/adapters/memory.cjs.map +0 -1
  74. package/dist/adapters/memory.mjs.map +0 -1
  75. package/dist/adapters/sessionStorage.cjs.map +0 -1
  76. package/dist/adapters/sessionStorage.mjs.map +0 -1
  77. package/dist/async-entry.d.ts.map +0 -1
  78. package/dist/async.cjs.map +0 -1
  79. package/dist/async.d.ts.map +0 -1
  80. package/dist/async.mjs.map +0 -1
  81. package/dist/batch.d.ts.map +0 -1
  82. package/dist/compose.d.ts.map +0 -1
  83. package/dist/computed-entry.d.ts.map +0 -1
  84. package/dist/computed.cjs.map +0 -1
  85. package/dist/computed.d.ts.map +0 -1
  86. package/dist/computed.mjs.map +0 -1
  87. package/dist/devtools/history.d.ts.map +0 -1
  88. package/dist/devtools/index.d.ts.map +0 -1
  89. package/dist/devtools/redux-bridge.d.ts.map +0 -1
  90. package/dist/devtools/snapshots.d.ts.map +0 -1
  91. package/dist/devtools/withDevtools.d.ts.map +0 -1
  92. package/dist/devtools.cjs.map +0 -1
  93. package/dist/devtools.mjs.map +0 -1
  94. package/dist/extensions/noop.d.ts.map +0 -1
  95. package/dist/index.cjs.js +0 -118
  96. package/dist/index.cjs.js.map +0 -1
  97. package/dist/index.cjs.map +0 -1
  98. package/dist/index.d.ts.map +0 -1
  99. package/dist/index.esm.js +0 -116
  100. package/dist/index.esm.js.map +0 -1
  101. package/dist/index.mjs.map +0 -1
  102. package/dist/persist/adapters/indexedDB.d.ts.map +0 -1
  103. package/dist/persist/adapters/localStorage.d.ts.map +0 -1
  104. package/dist/persist/adapters/memory.d.ts.map +0 -1
  105. package/dist/persist/adapters/sessionStorage.d.ts.map +0 -1
  106. package/dist/persist/debounce.d.ts.map +0 -1
  107. package/dist/persist/hydrate.d.ts.map +0 -1
  108. package/dist/persist/index.d.ts.map +0 -1
  109. package/dist/persist/serialize.d.ts.map +0 -1
  110. package/dist/persist.cjs.map +0 -1
  111. package/dist/persist.mjs.map +0 -1
  112. package/dist/proxy.d.ts.map +0 -1
  113. package/dist/registry-D3X0HSbl.js +0 -26
  114. package/dist/registry-D3X0HSbl.js.map +0 -1
  115. package/dist/registry-RDjbeJdx.js +0 -29
  116. package/dist/registry-RDjbeJdx.js.map +0 -1
  117. package/dist/registry-qtr1UpFU.js.map +0 -1
  118. package/dist/registry-zaKZ1P-s.js.map +0 -1
  119. package/dist/registry.d.ts.map +0 -1
  120. package/dist/signals/createSignal.d.ts.map +0 -1
  121. package/dist/signals/index.d.ts.map +0 -1
  122. package/dist/signals/useSignal.d.ts.map +0 -1
  123. package/dist/signals.cjs.map +0 -1
  124. package/dist/signals.mjs.map +0 -1
  125. package/dist/stats.html +0 -4949
  126. package/dist/store.d.ts.map +0 -1
  127. package/dist/sync/channel.d.ts.map +0 -1
  128. package/dist/sync/index.d.ts.map +0 -1
  129. package/dist/sync/protocol.d.ts.map +0 -1
  130. package/dist/sync/withSync.d.ts.map +0 -1
  131. package/dist/sync.cjs.map +0 -1
  132. package/dist/sync.mjs.map +0 -1
  133. package/dist/types.d.ts.map +0 -1
  134. package/rollup.config.mjs +0 -44
  135. package/src/async-entry.ts +0 -6
  136. package/src/async.ts +0 -240
  137. package/src/batch.ts +0 -33
  138. package/src/compose.ts +0 -50
  139. package/src/computed-entry.ts +0 -6
  140. package/src/computed.ts +0 -187
  141. package/src/devtools/history.ts +0 -103
  142. package/src/devtools/index.ts +0 -5
  143. package/src/devtools/redux-bridge.ts +0 -70
  144. package/src/devtools/snapshots.ts +0 -54
  145. package/src/devtools/withDevtools.ts +0 -196
  146. package/src/extensions/noop.ts +0 -12
  147. package/src/index.ts +0 -4
  148. package/src/persist/adapters/indexedDB.ts +0 -114
  149. package/src/persist/adapters/localStorage.ts +0 -28
  150. package/src/persist/adapters/memory.ts +0 -26
  151. package/src/persist/adapters/sessionStorage.ts +0 -28
  152. package/src/persist/debounce.ts +0 -28
  153. package/src/persist/hydrate.ts +0 -60
  154. package/src/persist/index.ts +0 -141
  155. package/src/persist/serialize.ts +0 -60
  156. package/src/proxy.ts +0 -87
  157. package/src/registry.ts +0 -67
  158. package/src/signals/createSignal.ts +0 -81
  159. package/src/signals/index.ts +0 -20
  160. package/src/signals/useSignal.ts +0 -18
  161. package/src/store.ts +0 -250
  162. package/src/sync/channel.ts +0 -15
  163. package/src/sync/index.ts +0 -3
  164. package/src/sync/protocol.ts +0 -18
  165. package/src/sync/withSync.ts +0 -147
  166. package/src/types.ts +0 -159
  167. package/tests/async.test.ts +0 -1100
  168. package/tests/batch.test.ts +0 -41
  169. package/tests/compose.test.ts +0 -209
  170. package/tests/computed.test.ts +0 -867
  171. package/tests/devtools.test.ts +0 -1039
  172. package/tests/integration/persist.integration.test.ts +0 -258
  173. package/tests/integration/signals.integration.test.ts +0 -309
  174. package/tests/integration.test.ts +0 -278
  175. package/tests/persist/adapters/indexedDB.adapter.test.ts +0 -185
  176. package/tests/persist/adapters/localStorage.adapter.test.ts +0 -105
  177. package/tests/persist/adapters/memory.adapter.test.ts +0 -112
  178. package/tests/persist/adapters/sessionStorage.adapter.test.ts +0 -128
  179. package/tests/persist/debounce.test.ts +0 -121
  180. package/tests/persist/hydrate.test.ts +0 -120
  181. package/tests/persist/migrate.test.ts +0 -208
  182. package/tests/persist/persist.test.ts +0 -357
  183. package/tests/persist/serialize.test.ts +0 -128
  184. package/tests/proxy.test.ts +0 -473
  185. package/tests/registry.test.ts +0 -67
  186. package/tests/signals/derived.test.ts +0 -244
  187. package/tests/signals/inference.test.ts +0 -108
  188. package/tests/signals/signal.test.ts +0 -348
  189. package/tests/signals/useSignal.test.tsx +0 -275
  190. package/tests/store.test.ts +0 -482
  191. package/tests/stress.test.ts +0 -268
  192. package/tests/sync.test.ts +0 -576
  193. package/tests/types.test.ts +0 -32
  194. package/tests/v0.3.test.ts +0 -813
  195. package/tree-shake-test.js +0 -1
  196. package/tsconfig.json +0 -15
  197. package/vitest.config.ts +0 -22
  198. package/vitest_play.ts +0 -7
@@ -1,244 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
- import { createStore } from '../../src/store';
3
- import { signal } from '../../src/signals/createSignal';
4
- import type { Store } from '../../src/types';
5
-
6
- describe('derived signals', () => {
7
- interface State {
8
- count: number;
9
- text: string;
10
- active: boolean;
11
- items: number[];
12
- }
13
-
14
- let store: Store<State>;
15
- let unsubscribes: (() => void)[] = [];
16
-
17
- beforeEach(() => {
18
- store = createStore<State>({
19
- count: 10,
20
- text: 'hello',
21
- active: true,
22
- items: [1, 2, 3],
23
- });
24
- unsubscribes = [];
25
- });
26
-
27
- afterEach(() => {
28
- unsubscribes.forEach((unsub) => unsub());
29
- });
30
-
31
- describe('get() — value transformation', () => {
32
- it('returns transform(storeValue) not the raw storeValue', () => {
33
- const sig = signal(store, 'count', (v) => v * 2);
34
- expect(sig.get()).toBe(20);
35
- });
36
-
37
- it('returns correct result for numeric transform (x => x * 2)', () => {
38
- const sig = signal(store, 'count', (x) => x * 2);
39
- expect(sig.get()).toBe(20);
40
- });
41
-
42
- it('returns correct result for string transform (x => x.toUpperCase())', () => {
43
- const sig = signal(store, 'text', (x) => x.toUpperCase());
44
- expect(sig.get()).toBe('HELLO');
45
- });
46
-
47
- it('returns correct result for boolean transform (x => !x)', () => {
48
- const sig = signal(store, 'active', (x) => !x);
49
- expect(sig.get()).toBe(false);
50
- });
51
-
52
- it('returns correct result for object mapping (x => ({ doubled: x * 2 }))', () => {
53
- const sig = signal(store, 'count', (x) => ({ doubled: x * 2 }));
54
- expect(sig.get()).toEqual({ doubled: 20 });
55
- });
56
-
57
- it('returns correct result for array transform (x => [...x].reverse())', () => {
58
- const sig = signal(store, 'items', (x) => [...x].reverse());
59
- expect(sig.get()).toEqual([3, 2, 1]);
60
- });
61
-
62
- it('updates correctly when the underlying store key changes', () => {
63
- const sig = signal(store, 'count', (v) => v + 1);
64
- store.setState({ count: 50 });
65
- expect(sig.get()).toBe(51);
66
- });
67
-
68
- it('does NOT update when an unrelated key changes', () => {
69
- const sig = signal(store, 'count', (v) => v * 1);
70
- store.setState({ text: 'changed' });
71
- expect(sig.get()).toBe(10);
72
- });
73
- });
74
-
75
- describe('subscribe() — transform-aware filtering', () => {
76
- it('notifies listener when underlying key changes AND transform output changes', () => {
77
- const sig = signal(store, 'count', (v) => v % 2 === 0);
78
- const listener = vi.fn();
79
- unsubscribes.push(sig.subscribe(listener));
80
-
81
- store.setState({ count: 11 }); // true -> false
82
- expect(listener).toHaveBeenCalledWith(false);
83
- });
84
-
85
- it('does NOT notify when underlying key changes but transform output is Object.is equal', () => {
86
- const sig = signal(store, 'count', () => true); // Always returns true
87
- const listener = vi.fn();
88
- unsubscribes.push(sig.subscribe(listener));
89
-
90
- store.setState({ count: 100 });
91
- expect(listener).not.toHaveBeenCalled();
92
- });
93
-
94
- it('does NOT notify when unrelated store key changes', () => {
95
- const sig = signal(store, 'count', (v) => v);
96
- const listener = vi.fn();
97
- unsubscribes.push(sig.subscribe(listener));
98
-
99
- store.setState({ text: 'unrelated' });
100
- expect(listener).not.toHaveBeenCalled();
101
- });
102
-
103
- it('DOES notify when transform output changes reference (new object/array each time)', () => {
104
- const sig = signal(store, 'count', (v) => ({ val: v }));
105
- const listener = vi.fn();
106
- unsubscribes.push(sig.subscribe(listener));
107
-
108
- store.setState({ count: 10 }); // value same (10), but transform returns NEW object
109
- expect(listener).toHaveBeenCalled();
110
- });
111
-
112
- it('listener receives the TRANSFORMED value, not the raw store value', () => {
113
- const sig = signal(store, 'count', (v) => v.toString());
114
- const listener = vi.fn();
115
- unsubscribes.push(sig.subscribe(listener));
116
-
117
- store.setState({ count: 500 });
118
- expect(listener).toHaveBeenCalledWith('500');
119
- });
120
-
121
- it('listener receives latest transform output after multiple store changes', () => {
122
- const sig = signal(store, 'count', (v) => v * 10);
123
- const listener = vi.fn();
124
- unsubscribes.push(sig.subscribe(listener));
125
-
126
- store.setState({ count: 1 });
127
- store.setState({ count: 2 });
128
- expect(listener).toHaveBeenLastCalledWith(20);
129
- });
130
- });
131
-
132
- describe('subscribe() — same rules as standard signal', () => {
133
- it('unsubscribe stops notifications', () => {
134
- const sig = signal(store, 'count', (v) => v * 2);
135
- const listener = vi.fn();
136
- const unsub = sig.subscribe(listener);
137
- unsub();
138
- store.setState({ count: 20 });
139
- expect(listener).not.toHaveBeenCalled();
140
- });
141
-
142
- it('multiple subscribers all receive transform output', () => {
143
- const sig = signal(store, 'count', (v) => v + 1);
144
- const l1 = vi.fn();
145
- const l2 = vi.fn();
146
- unsubscribes.push(sig.subscribe(l1));
147
- unsubscribes.push(sig.subscribe(l2));
148
-
149
- store.setState({ count: 100 });
150
- expect(l1).toHaveBeenCalledWith(101);
151
- expect(l2).toHaveBeenCalledWith(101);
152
- });
153
-
154
- it('removing one subscriber does not affect others', () => {
155
- const sig = signal(store, 'count', (v) => v);
156
- const l1 = vi.fn();
157
- const l2 = vi.fn();
158
- const unsub1 = sig.subscribe(l1);
159
- unsubscribes.push(sig.subscribe(l2));
160
-
161
- unsub1();
162
- store.setState({ count: 5 });
163
- expect(l1).not.toHaveBeenCalled();
164
- expect(l2).toHaveBeenCalledWith(5);
165
- });
166
- });
167
-
168
- describe('set() — read-only enforcement', () => {
169
- it('throws with EXACT message regardless of what value is passed', () => {
170
- const sig = signal(store, 'count', (v) => v * 2);
171
- const errorMsg = 'Storve: cannot call set() on a derived signal. Derived signals are read-only.';
172
-
173
- const setter = sig as unknown as { set: (v: unknown) => void };
174
- expect(() => setter.set(100)).toThrow(errorMsg);
175
- expect(() => setter.set('hi')).toThrow(errorMsg);
176
- expect(() => setter.set((v: unknown) => v)).toThrow(errorMsg);
177
- expect(() => setter.set(null)).toThrow(errorMsg);
178
- });
179
-
180
- it('throw does not corrupt store state — store is unchanged after throw', () => {
181
- const sig = signal(store, 'count', (v) => v * 2);
182
- try { (sig as unknown as { set: (v: number) => void }).set(999); } catch { /* expected */ }
183
- expect(store.getState().count).toBe(10);
184
- });
185
-
186
- it('throw does not break existing signal subscribers', () => {
187
- const sig = signal(store, 'count', (v) => v * 2);
188
- const listener = vi.fn();
189
- unsubscribes.push(sig.subscribe(listener));
190
-
191
- try { (sig as unknown as { set: (v: number) => void }).set(999); } catch { /* expected */ }
192
-
193
- store.setState({ count: 11 });
194
- expect(listener).toHaveBeenCalledWith(22);
195
- });
196
- });
197
-
198
- describe('_derived flag', () => {
199
- it('is true on every derived signal', () => {
200
- const sig = signal(store, 'count', (v) => v);
201
- expect(sig._derived).toBe(true);
202
- });
203
-
204
- it('standard signal has _derived === false (contrast check)', () => {
205
- const sig = signal(store, 'count');
206
- expect(sig._derived).toBe(false);
207
- });
208
- });
209
-
210
- describe('Composition', () => {
211
- it('derived signal on top of a key that is itself updated by another signal\'s set()', () => {
212
- const baseSig = signal(store, 'count');
213
- const derivedSig = signal(store, 'count', (v) => v * 2);
214
-
215
- baseSig.set(50);
216
- expect(derivedSig.get()).toBe(100);
217
- });
218
-
219
- it('two derived signals on same key with different transforms are independent', () => {
220
- const sigA = signal(store, 'count', (v) => v * 2);
221
- const sigB = signal(store, 'count', (v) => v + 10);
222
-
223
- store.setState({ count: 5 });
224
- expect(sigA.get()).toBe(10);
225
- expect(sigB.get()).toBe(15);
226
- });
227
-
228
- it('each fires only when their own transform output changes', () => {
229
- const sigA = signal(store, 'count', (v) => v > 10);
230
- const sigB = signal(store, 'count', (v) => v > 20);
231
- const lA = vi.fn();
232
- const lB = vi.fn();
233
- unsubscribes.push(sigA.subscribe(lA));
234
- unsubscribes.push(sigB.subscribe(lB));
235
-
236
- store.setState({ count: 15 }); // lA fires (false -> true), lB doesn't (false -> false)
237
- expect(lA).toHaveBeenCalledWith(true);
238
- expect(lB).not.toHaveBeenCalled();
239
-
240
- store.setState({ count: 25 }); // lA doesn't fire (true -> true), lB fires (false -> true)
241
- expect(lB).toHaveBeenCalledWith(true);
242
- });
243
- });
244
- });
@@ -1,108 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { createStore } from '../../src/store';
3
- import { signal } from '../../src/signals/createSignal';
4
-
5
- describe('signal inference', () => {
6
- const store = createStore({
7
- count: 0,
8
- name: 'alice',
9
- active: false,
10
- items: [1, 2, 3] as number[],
11
- user: { id: 1, role: 'admin' }
12
- });
13
-
14
- describe('valid inference', () => {
15
- it('signal(store, \'count\') infers Signal<number>', () => {
16
- const countSig = signal(store, 'count');
17
- expect(countSig.get()).toBe(0);
18
- // Verify type via assignment
19
- const n: number = countSig.get();
20
- expect(n).toBe(0);
21
- });
22
-
23
- it('signal(store, \'name\') infers Signal<string>', () => {
24
- const nameSig = signal(store, 'name');
25
- expect(nameSig.get()).toBe('alice');
26
- const s: string = nameSig.get();
27
- expect(s).toBe('alice');
28
- });
29
-
30
- it('signal(store, \'active\') infers Signal<boolean>', () => {
31
- const activeSig = signal(store, 'active');
32
- expect(activeSig.get()).toBe(false);
33
- const b: boolean = activeSig.get();
34
- expect(b).toBe(false);
35
- });
36
-
37
- it('signal(store, \'items\') infers Signal<number[]>', () => {
38
- const itemsSig = signal(store, 'items');
39
- expect(Array.isArray(itemsSig.get())).toBe(true);
40
- const arr: number[] = itemsSig.get();
41
- expect(arr).toEqual([1, 2, 3]);
42
- });
43
-
44
- it('signal(store, \'user\') infers Signal<{id: number, role: string}>', () => {
45
- const userSig = signal(store, 'user');
46
- expect(userSig.get().id).toBe(1);
47
- const user: { id: number; role: string } = userSig.get();
48
- expect(user.role).toBe('admin');
49
- });
50
-
51
- it('signal(store, \'count\', v => v * 2) infers Signal<number>', () => {
52
- const doubleSig = signal(store, 'count', (v) => v * 2);
53
- expect(doubleSig.get()).toBe(0);
54
- const n: number = doubleSig.get();
55
- expect(n).toBe(0);
56
- });
57
-
58
- it('signal(store, \'count\', v => v.toString()) infers Signal<string>', () => {
59
- const strSig = signal(store, 'count', (v) => v.toString());
60
- expect(typeof strSig.get()).toBe('string');
61
- const s: string = strSig.get();
62
- expect(s).toBe('0');
63
- });
64
-
65
- it('signal(store, \'count\', v => v > 0) infers Signal<boolean>', () => {
66
- const boolSig = signal(store, 'count', (v) => v > 0);
67
- expect(typeof boolSig.get()).toBe('boolean');
68
- const b: boolean = boolSig.get();
69
- expect(b).toBe(false);
70
- });
71
-
72
- it('signal(store, \'name\', v => v.length) infers Signal<number>', () => {
73
- const lenSig = signal(store, 'name', (v) => v.length);
74
- expect(lenSig.get()).toBe(5);
75
- const n: number = lenSig.get();
76
- expect(n).toBe(5);
77
- });
78
-
79
- it('signal(store, \'items\', v => v.map(x => x * 2)) infers Signal<number[]>', () => {
80
- const mappedSig = signal(store, 'items', (v) => v.map((x) => x * 2));
81
- expect(mappedSig.get()).toEqual([2, 4, 6]);
82
- const arr: number[] = mappedSig.get();
83
- expect(arr).toEqual([2, 4, 6]);
84
- });
85
- });
86
-
87
- describe('invalid usage', () => {
88
- it('should fail compilation for invalid keys and types', () => {
89
- const countSig = signal(store, 'count');
90
- const strSig = signal(store, 'count', (v) => v.toString());
91
-
92
- // @ts-expect-error — 'nonExistent' is not a key of the store
93
- signal(store, 'nonExistent');
94
-
95
- // @ts-expect-error — 123 is not a key of the store
96
- signal(store, 123);
97
-
98
- // @ts-expect-error — set() receives wrong type: count is number, not string
99
- countSig.set('hello');
100
-
101
- // @ts-expect-error — set() updater must return number, not string
102
- countSig.set((prev) => prev.toString());
103
-
104
- // @ts-expect-error — set() on derived signal accepts wrong type
105
- expect(() => { strSig.set(42); }).toThrow();
106
- });
107
- });
108
- });