synstate 3.0.0 → 3.0.2

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 (148) hide show
  1. package/README.md +1 -1
  2. package/dist/core/base/create-child-observable.d.mts.map +1 -1
  3. package/dist/core/base/create-child-observable.mjs +169 -140
  4. package/dist/core/base/create-child-observable.mjs.map +1 -1
  5. package/dist/core/base/create-observable-base.d.mts.map +1 -1
  6. package/dist/core/base/create-observable-base.mjs +155 -152
  7. package/dist/core/base/create-observable-base.mjs.map +1 -1
  8. package/dist/core/base/create-root-observable.mjs +48 -34
  9. package/dist/core/base/create-root-observable.mjs.map +1 -1
  10. package/dist/core/base/index.mjs +3 -3
  11. package/dist/core/base/index.mjs.map +1 -1
  12. package/dist/core/combine/combine.mjs +129 -37
  13. package/dist/core/combine/combine.mjs.map +1 -1
  14. package/dist/core/combine/index.mjs +4 -4
  15. package/dist/core/combine/index.mjs.map +1 -1
  16. package/dist/core/combine/merge.mjs +75 -24
  17. package/dist/core/combine/merge.mjs.map +1 -1
  18. package/dist/core/combine/zip.mjs +120 -39
  19. package/dist/core/combine/zip.mjs.map +1 -1
  20. package/dist/core/create/counter.mjs +81 -45
  21. package/dist/core/create/counter.mjs.map +1 -1
  22. package/dist/core/create/from-abortable-promise.mjs +63 -38
  23. package/dist/core/create/from-abortable-promise.mjs.map +1 -1
  24. package/dist/core/create/from-promise.mjs +67 -25
  25. package/dist/core/create/from-promise.mjs.map +1 -1
  26. package/dist/core/create/from-subscribable.mjs +70 -26
  27. package/dist/core/create/from-subscribable.mjs.map +1 -1
  28. package/dist/core/create/index.mjs +8 -8
  29. package/dist/core/create/index.mjs.map +1 -1
  30. package/dist/core/create/just.mjs +36 -13
  31. package/dist/core/create/just.mjs.map +1 -1
  32. package/dist/core/create/source.mjs +15 -19
  33. package/dist/core/create/source.mjs.map +1 -1
  34. package/dist/core/create/timer.mjs +66 -37
  35. package/dist/core/create/timer.mjs.map +1 -1
  36. package/dist/core/index.mjs +6 -41
  37. package/dist/core/index.mjs.map +1 -1
  38. package/dist/core/operators/audit.mjs +126 -39
  39. package/dist/core/operators/audit.mjs.map +1 -1
  40. package/dist/core/operators/debounce.mjs +114 -37
  41. package/dist/core/operators/debounce.mjs.map +1 -1
  42. package/dist/core/operators/filter.mjs +39 -24
  43. package/dist/core/operators/filter.mjs.map +1 -1
  44. package/dist/core/operators/index.mjs +18 -18
  45. package/dist/core/operators/index.mjs.map +1 -1
  46. package/dist/core/operators/map.mjs +74 -26
  47. package/dist/core/operators/map.mjs.map +1 -1
  48. package/dist/core/operators/merge-map.mjs +128 -35
  49. package/dist/core/operators/merge-map.mjs.map +1 -1
  50. package/dist/core/operators/pairwise.mjs +73 -23
  51. package/dist/core/operators/pairwise.mjs.map +1 -1
  52. package/dist/core/operators/scan.mjs +59 -15
  53. package/dist/core/operators/scan.mjs.map +1 -1
  54. package/dist/core/operators/skip-if-no-change.mjs +89 -31
  55. package/dist/core/operators/skip-if-no-change.mjs.map +1 -1
  56. package/dist/core/operators/skip-until.mjs +71 -29
  57. package/dist/core/operators/skip-until.mjs.map +1 -1
  58. package/dist/core/operators/skip-while.mjs +79 -27
  59. package/dist/core/operators/skip-while.mjs.map +1 -1
  60. package/dist/core/operators/switch-map.mjs +118 -31
  61. package/dist/core/operators/switch-map.mjs.map +1 -1
  62. package/dist/core/operators/take-until.mjs +70 -35
  63. package/dist/core/operators/take-until.mjs.map +1 -1
  64. package/dist/core/operators/take-while.mjs +97 -25
  65. package/dist/core/operators/take-while.mjs.map +1 -1
  66. package/dist/core/operators/throttle.mjs +108 -38
  67. package/dist/core/operators/throttle.mjs.map +1 -1
  68. package/dist/core/operators/with-buffered-from.mjs +94 -47
  69. package/dist/core/operators/with-buffered-from.mjs.map +1 -1
  70. package/dist/core/operators/with-current-value-from.mjs +78 -23
  71. package/dist/core/operators/with-current-value-from.mjs.map +1 -1
  72. package/dist/core/operators/with-initial-value.mjs +64 -14
  73. package/dist/core/operators/with-initial-value.mjs.map +1 -1
  74. package/dist/core/predefined/index.mjs +2 -12
  75. package/dist/core/predefined/index.mjs.map +1 -1
  76. package/dist/core/predefined/operators/attach-index.mjs +55 -7
  77. package/dist/core/predefined/operators/attach-index.mjs.map +1 -1
  78. package/dist/core/predefined/operators/index.mjs +12 -12
  79. package/dist/core/predefined/operators/index.mjs.map +1 -1
  80. package/dist/core/predefined/operators/map-optional.mjs +48 -5
  81. package/dist/core/predefined/operators/map-optional.mjs.map +1 -1
  82. package/dist/core/predefined/operators/map-result-err.mjs +48 -5
  83. package/dist/core/predefined/operators/map-result-err.mjs.map +1 -1
  84. package/dist/core/predefined/operators/map-result-ok.mjs +48 -5
  85. package/dist/core/predefined/operators/map-result-ok.mjs.map +1 -1
  86. package/dist/core/predefined/operators/map-to.mjs +41 -6
  87. package/dist/core/predefined/operators/map-to.mjs.map +1 -1
  88. package/dist/core/predefined/operators/pluck.mjs +45 -7
  89. package/dist/core/predefined/operators/pluck.mjs.map +1 -1
  90. package/dist/core/predefined/operators/skip.mjs +49 -6
  91. package/dist/core/predefined/operators/skip.mjs.map +1 -1
  92. package/dist/core/predefined/operators/take.mjs +42 -6
  93. package/dist/core/predefined/operators/take.mjs.map +1 -1
  94. package/dist/core/predefined/operators/unwrap-optional.mjs +43 -8
  95. package/dist/core/predefined/operators/unwrap-optional.mjs.map +1 -1
  96. package/dist/core/predefined/operators/unwrap-result-err.mjs +41 -5
  97. package/dist/core/predefined/operators/unwrap-result-err.mjs.map +1 -1
  98. package/dist/core/predefined/operators/unwrap-result-ok.mjs +43 -8
  99. package/dist/core/predefined/operators/unwrap-result-ok.mjs.map +1 -1
  100. package/dist/core/types/id.mjs +2 -2
  101. package/dist/core/types/id.mjs.map +1 -1
  102. package/dist/core/types/index.mjs +7 -3
  103. package/dist/core/types/index.mjs.map +1 -1
  104. package/dist/core/types/observable-family.d.mts +2 -2
  105. package/dist/core/types/observable-family.d.mts.map +1 -1
  106. package/dist/core/types/observable-family.mjs +10 -2
  107. package/dist/core/types/observable-family.mjs.map +1 -1
  108. package/dist/core/types/observable-kind.mjs +2 -2
  109. package/dist/core/types/observable-kind.mjs.map +1 -1
  110. package/dist/core/types/observable.mjs +14 -6
  111. package/dist/core/types/observable.mjs.map +1 -1
  112. package/dist/core/types/timer.d.mts +11 -1
  113. package/dist/core/types/timer.d.mts.map +1 -1
  114. package/dist/core/types/timer.mjs +2 -2
  115. package/dist/core/types/timer.mjs.map +1 -1
  116. package/dist/core/types/types.mjs +9 -2
  117. package/dist/core/types/types.mjs.map +1 -1
  118. package/dist/core/utils/id-maker.mjs +10 -11
  119. package/dist/core/utils/id-maker.mjs.map +1 -1
  120. package/dist/core/utils/index.mjs +5 -5
  121. package/dist/core/utils/index.mjs.map +1 -1
  122. package/dist/core/utils/max-depth.mjs +7 -4
  123. package/dist/core/utils/max-depth.mjs.map +1 -1
  124. package/dist/core/utils/observable-utils.mjs +4 -7
  125. package/dist/core/utils/observable-utils.mjs.map +1 -1
  126. package/dist/core/utils/utils.mjs +32 -28
  127. package/dist/core/utils/utils.mjs.map +1 -1
  128. package/dist/entry-point.mjs +2 -46
  129. package/dist/entry-point.mjs.map +1 -1
  130. package/dist/index.mjs +3 -46
  131. package/dist/index.mjs.map +1 -1
  132. package/dist/utils/collect-to-array.mjs +8 -13
  133. package/dist/utils/collect-to-array.mjs.map +1 -1
  134. package/dist/utils/create-boolean-state.mjs +47 -22
  135. package/dist/utils/create-boolean-state.mjs.map +1 -1
  136. package/dist/utils/create-event-emitter.mjs +67 -19
  137. package/dist/utils/create-event-emitter.mjs.map +1 -1
  138. package/dist/utils/create-reducer.mjs +54 -16
  139. package/dist/utils/create-reducer.mjs.map +1 -1
  140. package/dist/utils/create-state.mjs +54 -27
  141. package/dist/utils/create-state.mjs.map +1 -1
  142. package/dist/utils/index.mjs +6 -6
  143. package/dist/utils/index.mjs.map +1 -1
  144. package/package.json +14 -12
  145. package/src/core/base/create-child-observable.mts +6 -1
  146. package/src/core/base/create-observable-base.mts +8 -1
  147. package/src/core/types/observable-family.mts +53 -34
  148. package/src/core/types/timer.mts +11 -2
@@ -1 +1 @@
1
- {"version":3,"file":"collect-to-array.mjs","sources":["../../src/utils/collect-to-array.mts"],"sourcesContent":["import { type Observable } from '../core/index.mjs';\n\nexport const collectToArray = <A,>(\n observable: Observable<A>,\n): Promise<readonly A[]> =>\n new Promise<readonly A[]>((resolve) => {\n const mut_buffer: A[] = [];\n\n observable.subscribe(\n (value) => {\n mut_buffer.push(value);\n },\n () => {\n resolve(mut_buffer);\n },\n );\n });\n"],"names":[],"mappings":"AAEO,MAAM,iBAAiB,CAC5B,UAAA,KAEA,IAAI,OAAA,CAAsB,CAAC,OAAA,KAAY;AACrC,EAAA,MAAM,aAAkB,EAAC;AAEzB,EAAA,UAAA,CAAW,SAAA;AAAA,IACT,CAAC,KAAA,KAAU;AACT,MAAA,UAAA,CAAW,KAAK,KAAK,CAAA;AAAA,IACvB,CAAA;AAAA,IACA,MAAM;AACJ,MAAA,OAAA,CAAQ,UAAU,CAAA;AAAA,IACpB;AAAA,GACF;AACF,CAAC;;;;"}
1
+ {"version":3,"file":"collect-to-array.mjs","sourceRoot":"","sources":["../../src/utils/collect-to-array.mts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,UAAyB,EACF,EAAE,CACzB,IAAI,OAAO,CAAe,CAAC,OAAO,EAAE,EAAE;IACpC,MAAM,UAAU,GAAQ,EAAE,CAAC;IAE3B,UAAU,CAAC,SAAS,CAClB,CAAC,KAAK,EAAE,EAAE;QACR,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC,EACD,GAAG,EAAE;QACH,OAAO,CAAC,UAAU,CAAC,CAAC;IACtB,CAAC,CACF,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -1,25 +1,50 @@
1
1
  import { createState } from './create-state.mjs';
2
2
 
3
- const createBooleanState = (initialState) => {
4
- const [state, setState, { updateState, resetState, getSnapshot }] = createState(initialState);
5
- return [
6
- state,
7
- {
8
- setTrue: () => {
9
- setState(true);
10
- },
11
- setFalse: () => {
12
- setState(false);
13
- },
14
- toggle: () => updateState((s) => !s),
15
- setState,
16
- updateState,
17
- resetState,
18
- getSnapshot,
19
- initialState
20
- }
21
- ];
22
- };
23
3
 
24
- export { createBooleanState };
25
- //# sourceMappingURL=create-boolean-state.mjs.map
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+ export const createBooleanState = (initialState) => {
31
+ const [state, setState, { updateState, resetState, getSnapshot }] = createState(initialState);
32
+ return [
33
+ state,
34
+ {
35
+ setTrue: () => {
36
+ setState(true);
37
+ },
38
+ setFalse: () => {
39
+ setState(false);
40
+ },
41
+ toggle: () => updateState((s) => !s),
42
+ setState,
43
+ updateState,
44
+ resetState,
45
+ getSnapshot,
46
+ initialState,
47
+ },
48
+ ];
49
+ };
50
+ //# sourceMappingURL=create-boolean-state.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-boolean-state.mjs","sources":["../../src/utils/create-boolean-state.mts"],"sourcesContent":["import { type InitializedObservable } from '../core/index.mjs';\nimport { createState } from './create-state.mjs';\n\n/**\n * Creates a reactive boolean state with convenient methods for boolean operations.\n * Extends `createState` with boolean-specific helpers like `toggle`, `setTrue`, and `setFalse`.\n *\n * @param initialState - The initial boolean value\n * @returns A 2-element tuple: `[state, { setTrue, setFalse, toggle, setState, updateState, resetState, getSnapshot, initialState }]`\n *\n * @example\n * ```ts\n * import type * as React from 'react';\n * import { createBooleanState } from 'synstate';\n * import { useObservableValue } from 'synstate-react-hooks';\n *\n * // Menu drawer open/close state.\n * // setTrue and setFalse can be passed directly as callbacks\n * // — no need to create wrapper functions like `() => setState(true)`.\n * const [menuOpen$, { setTrue: openMenu, setFalse: closeMenu }] =\n * createBooleanState(false);\n *\n * const SampleComponent = (): React.JSX.Element => (\n * <MenuDrawer\n * open={useObservableValue(menuOpen$)}\n * onClose={closeMenu}\n * onOpen={openMenu}\n * />\n * );\n * ```\n */\n\nexport const createBooleanState = (\n initialState: boolean,\n): readonly [\n state: InitializedObservable<boolean>,\n utils: Readonly<{\n setTrue: () => void;\n setFalse: () => void;\n setState: (next: boolean) => boolean;\n toggle: () => boolean;\n updateState: (updateFn: (prev: boolean) => boolean) => boolean;\n resetState: () => boolean;\n getSnapshot: () => boolean;\n initialState: boolean;\n }>,\n] => {\n const [state, setState, { updateState, resetState, getSnapshot }] =\n createState(initialState);\n\n return [\n state,\n {\n setTrue: () => {\n setState(true);\n },\n setFalse: () => {\n setState(false);\n },\n toggle: () => updateState((s) => !s),\n setState,\n updateState,\n resetState,\n getSnapshot,\n initialState,\n },\n ] as const;\n};\n"],"names":[],"mappings":";;AAgCO,MAAM,kBAAA,GAAqB,CAChC,YAAA,KAaG;AACH,EAAA,MAAM,CAAC,KAAA,EAAO,QAAA,EAAU,EAAE,WAAA,EAAa,YAAY,WAAA,EAAa,CAAA,GAC9D,WAAA,CAAY,YAAY,CAAA;AAE1B,EAAA,OAAO;AAAA,IACL,KAAA;AAAA,IACA;AAAA,MACE,SAAS,MAAM;AACb,QAAA,QAAA,CAAS,IAAI,CAAA;AAAA,MACf,CAAA;AAAA,MACA,UAAU,MAAM;AACd,QAAA,QAAA,CAAS,KAAK,CAAA;AAAA,MAChB,CAAA;AAAA,MACA,QAAQ,MAAM,WAAA,CAAY,CAAC,CAAA,KAAM,CAAC,CAAC,CAAA;AAAA,MACnC,QAAA;AAAA,MACA,WAAA;AAAA,MACA,UAAA;AAAA,MACA,WAAA;AAAA,MACA;AAAA;AACF,GACF;AACF;;;;"}
1
+ {"version":3,"file":"create-boolean-state.mjs","sourceRoot":"","sources":["../../src/utils/create-boolean-state.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,YAAqB,EAarB,EAAE;IACF,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC,GAC/D,WAAW,CAAC,YAAY,CAAC,CAAC;IAE5B,OAAO;QACL,KAAK;QACL;YACE,OAAO,EAAE,GAAG,EAAE;gBACZ,QAAQ,CAAC,IAAI,CAAC,CAAC;YACjB,CAAC;YACD,QAAQ,EAAE,GAAG,EAAE;gBACb,QAAQ,CAAC,KAAK,CAAC,CAAC;YAClB,CAAC;YACD,MAAM,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;YACpC,QAAQ;YACR,WAAW;YACX,UAAU;YACV,WAAW;YACX,YAAY;SACb;KACO,CAAC;AACb,CAAC,CAAC"}
@@ -1,21 +1,69 @@
1
- import 'ts-data-forge';
2
- import '../core/utils/id-maker.mjs';
3
- import { source } from '../core/create/source.mjs';
4
-
5
- const createEventEmitter = () => {
6
- const src$ = source();
7
- const emitter = () => {
8
- src$.next(void 0);
9
- };
10
- return [src$, emitter];
11
- };
12
- const createValueEmitter = () => {
13
- const src$ = source();
14
- const emitter = (value) => {
15
- src$.next(value);
16
- };
17
- return [src$, emitter];
1
+ import { source } from '../core/index.mjs';
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+ export const createEventEmitter = () => {
30
+ const src$ = source();
31
+ const emitter = () => {
32
+ src$.next(undefined);
33
+ };
34
+ return [src$, emitter];
18
35
  };
19
36
 
20
- export { createEventEmitter, createValueEmitter };
21
- //# sourceMappingURL=create-event-emitter.mjs.map
37
+
38
+
39
+
40
+
41
+
42
+
43
+
44
+
45
+
46
+
47
+
48
+
49
+
50
+
51
+
52
+
53
+
54
+
55
+
56
+
57
+
58
+
59
+
60
+
61
+
62
+ export const createValueEmitter = () => {
63
+ const src$ = source();
64
+ const emitter = (value) => {
65
+ src$.next(value);
66
+ };
67
+ return [src$, emitter];
68
+ };
69
+ //# sourceMappingURL=create-event-emitter.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-event-emitter.mjs","sources":["../../src/utils/create-event-emitter.mts"],"sourcesContent":["import { source, type Observable } from '../core/index.mjs';\n\n/**\n * Creates an event emitter for void events (events without payload).\n * Returns a tuple of [observable, emitter function].\n *\n * @returns A tuple containing the observable and the emitter function\n *\n * @example\n * ```ts\n * const [click$, emitClick] = createEventEmitter();\n *\n * const mut_clickCount = { value: 0 };\n *\n * click$.subscribe(() => {\n * mut_clickCount.value += 1;\n * });\n *\n * emitClick(); // logs: Clicked!\n *\n * assert.deepStrictEqual(mut_clickCount.value, 1);\n *\n * emitClick();\n *\n * emitClick();\n *\n * assert.deepStrictEqual(mut_clickCount.value, 3);\n * ```\n */\nexport const createEventEmitter = (): readonly [\n Observable<void>,\n () => void,\n] => {\n const src$ = source<undefined>();\n\n const emitter = (): void => {\n src$.next(undefined);\n };\n\n return [src$, emitter];\n};\n\n/**\n * Creates an event emitter with typed payload.\n * Returns a tuple of [observable, emitter function].\n *\n * @template A - The type of the event payload\n * @returns A tuple containing the observable and the emitter function\n *\n * @example\n * ```ts\n * const [message$, emitMessage] = createValueEmitter<string>();\n *\n * const messageHistory: string[] = [];\n *\n * message$.subscribe((msg) => {\n * messageHistory.push(msg);\n * });\n *\n * emitMessage('Hello'); // logs: Hello\n *\n * assert.deepStrictEqual(messageHistory, ['Hello']);\n *\n * emitMessage('World');\n *\n * assert.deepStrictEqual(messageHistory, ['Hello', 'World']);\n * ```\n */\nexport const createValueEmitter = <A,>(): readonly [\n Observable<A>,\n (value: A) => void,\n] => {\n const src$ = source<A>();\n\n const emitter = (value: A): void => {\n src$.next(value);\n };\n\n return [src$, emitter];\n};\n"],"names":[],"mappings":";;;;AA6BO,MAAM,qBAAqB,MAG7B;AACH,EAAA,MAAM,OAAO,MAAA,EAAkB;AAE/B,EAAA,MAAM,UAAU,MAAY;AAC1B,IAAA,IAAA,CAAK,KAAK,MAAS,CAAA;AAAA,EACrB,CAAA;AAEA,EAAA,OAAO,CAAC,MAAM,OAAO,CAAA;AACvB;AA4BO,MAAM,qBAAqB,MAG7B;AACH,EAAA,MAAM,OAAO,MAAA,EAAU;AAEvB,EAAA,MAAM,OAAA,GAAU,CAAC,KAAA,KAAmB;AAClC,IAAA,IAAA,CAAK,KAAK,KAAK,CAAA;AAAA,EACjB,CAAA;AAEA,EAAA,OAAO,CAAC,MAAM,OAAO,CAAA;AACvB;;;;"}
1
+ {"version":3,"file":"create-event-emitter.mjs","sourceRoot":"","sources":["../../src/utils/create-event-emitter.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAmB,MAAM,mBAAmB,CAAC;AAE5D;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAGhC,EAAE;IACF,MAAM,IAAI,GAAG,MAAM,EAAa,CAAC;IAEjC,MAAM,OAAO,GAAG,GAAS,EAAE;QACzB,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACvB,CAAC,CAAC;IAEF,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AACzB,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAGhC,EAAE;IACF,MAAM,IAAI,GAAG,MAAM,EAAK,CAAC;IAEzB,MAAM,OAAO,GAAG,CAAC,KAAQ,EAAQ,EAAE;QACjC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnB,CAAC,CAAC;IAEF,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AACzB,CAAC,CAAC"}
@@ -1,17 +1,55 @@
1
- import 'ts-data-forge';
2
- import '../core/utils/id-maker.mjs';
3
- import { source } from '../core/create/source.mjs';
4
-
5
- const createReducer = (reducer, initialState) => {
6
- const state = source(initialState);
7
- const dispatch = (action) => {
8
- const nextState = reducer(state.getSnapshot().value, action);
9
- state.next(nextState);
10
- return nextState;
11
- };
12
- const getSnapshot = () => state.getSnapshot().value;
13
- return [state, dispatch, { getSnapshot, initialState }];
14
- };
1
+ import { source } from '../core/index.mjs';
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
15
23
 
16
- export { createReducer };
17
- //# sourceMappingURL=create-reducer.mjs.map
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41
+
42
+
43
+
44
+
45
+ export const createReducer = (reducer, initialState) => {
46
+ const state = source(initialState);
47
+ const dispatch = (action) => {
48
+ const nextState = reducer(state.getSnapshot().value, action);
49
+ state.next(nextState);
50
+ return nextState;
51
+ };
52
+ const getSnapshot = () => state.getSnapshot().value;
53
+ return [state, dispatch, { getSnapshot, initialState }];
54
+ };
55
+ //# sourceMappingURL=create-reducer.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-reducer.mjs","sources":["../../src/utils/create-reducer.mts"],"sourcesContent":["import { type Reducer } from 'ts-type-forge';\nimport { source, type InitializedObservable } from '../core/index.mjs';\n\n/**\n * Creates a reducer-based state management container following the Redux pattern.\n * Actions are dispatched to update the state according to the reducer function.\n *\n * @template S - The type of the state\n * @template A - The type of actions\n * @param reducer - A pure function that takes current state and action, returns new state\n * @param initialState - The initial value of the state\n * @returns A 3-element tuple: `[state, dispatch, { getSnapshot, initialState }]`\n *\n * @example\n * ```ts\n * const [state, dispatch] = createReducer(\n * (s, action: Readonly<{ type: 'increment' } | { type: 'decrement' }>) => {\n * switch (action.type) {\n * case 'increment':\n * return s + 1;\n * case 'decrement':\n * return s - 1;\n * }\n * },\n * 0,\n * );\n *\n * const stateHistory: number[] = [];\n *\n * state.subscribe((value: number) => {\n * stateHistory.push(value);\n * });\n *\n * assert.deepStrictEqual(stateHistory, [0]);\n *\n * dispatch({ type: 'increment' }); // logs: 1\n *\n * assert.deepStrictEqual(stateHistory, [0, 1]);\n *\n * dispatch({ type: 'increment' });\n *\n * dispatch({ type: 'decrement' });\n *\n * assert.deepStrictEqual(stateHistory, [0, 1, 2, 1]);\n * ```\n */\nexport const createReducer = <S, A>(\n reducer: Reducer<S, A>,\n initialState: S,\n): readonly [\n state: InitializedObservable<S>,\n dispatch: (action: A) => S,\n utils: Readonly<{\n getSnapshot: () => S;\n initialState: S;\n }>,\n] => {\n const state = source<S>(initialState);\n\n const dispatch = (action: A): S => {\n const nextState = reducer(state.getSnapshot().value, action);\n\n state.next(nextState);\n\n return nextState;\n };\n\n const getSnapshot = (): S => state.getSnapshot().value;\n\n return [state, dispatch, { getSnapshot, initialState }] as const;\n};\n"],"names":[],"mappings":";;;;AA8CO,MAAM,aAAA,GAAgB,CAC3B,OAAA,EACA,YAAA,KAQG;AACH,EAAA,MAAM,KAAA,GAAQ,OAAU,YAAY,CAAA;AAEpC,EAAA,MAAM,QAAA,GAAW,CAAC,MAAA,KAAiB;AACjC,IAAA,MAAM,YAAY,OAAA,CAAQ,KAAA,CAAM,WAAA,EAAY,CAAE,OAAO,MAAM,CAAA;AAE3D,IAAA,KAAA,CAAM,KAAK,SAAS,CAAA;AAEpB,IAAA,OAAO,SAAA;AAAA,EACT,CAAA;AAEA,EAAA,MAAM,WAAA,GAAc,MAAS,KAAA,CAAM,WAAA,EAAY,CAAE,KAAA;AAEjD,EAAA,OAAO,CAAC,KAAA,EAAO,QAAA,EAAU,EAAE,WAAA,EAAa,cAAc,CAAA;AACxD;;;;"}
1
+ {"version":3,"file":"create-reducer.mjs","sourceRoot":"","sources":["../../src/utils/create-reducer.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAA8B,MAAM,mBAAmB,CAAC;AAEvE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,OAAsB,EACtB,YAAe,EAQf,EAAE;IACF,MAAM,KAAK,GAAG,MAAM,CAAI,YAAY,CAAC,CAAC;IAEtC,MAAM,QAAQ,GAAG,CAAC,MAAS,EAAK,EAAE;QAChC,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAE7D,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAEtB,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC;IAEF,MAAM,WAAW,GAAG,GAAM,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC;IAEvD,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,WAAW,EAAE,YAAY,EAAE,CAAU,CAAC;AACnE,CAAC,CAAC"}
@@ -1,32 +1,59 @@
1
1
  import { createReducer } from './create-reducer.mjs';
2
-
3
2
  const reducer = (state, action) => {
4
- switch (action.type) {
5
- case "set":
6
- return action.nextState;
7
- case "update":
8
- return action.updateFn(state);
9
- }
10
- };
11
- const createState = (initialState) => {
12
- const [state, dispatch, { getSnapshot }] = createReducer(
13
- reducer,
14
- initialState
15
- );
16
- const updateState = (updateFn) => dispatch({ type: "update", updateFn });
17
- const setState = (nextState) => dispatch({ type: "set", nextState });
18
- const resetState = () => dispatch({ type: "set", nextState: initialState });
19
- return [
20
- state,
21
- setState,
22
- {
23
- updateState,
24
- resetState,
25
- getSnapshot,
26
- initialState
3
+ switch (action.type) {
4
+ case 'set':
5
+ return action.nextState;
6
+ case 'update':
7
+ return action.updateFn(state);
27
8
  }
28
- ];
29
9
  };
30
10
 
31
- export { createState };
32
- //# sourceMappingURL=create-state.mjs.map
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41
+
42
+
43
+ export const createState = (initialState) => {
44
+ const [state, dispatch, { getSnapshot }] = createReducer(reducer, initialState);
45
+ const updateState = (updateFn) => dispatch({ type: 'update', updateFn });
46
+ const setState = (nextState) => dispatch({ type: 'set', nextState });
47
+ const resetState = () => dispatch({ type: 'set', nextState: initialState });
48
+ return [
49
+ state,
50
+ setState,
51
+ {
52
+ updateState,
53
+ resetState,
54
+ getSnapshot,
55
+ initialState,
56
+ },
57
+ ];
58
+ };
59
+ //# sourceMappingURL=create-state.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-state.mjs","sources":["../../src/utils/create-state.mts"],"sourcesContent":["import { type InitializedObservable } from '../core/index.mjs';\nimport { createReducer } from './create-reducer.mjs';\n\ntype Action<S> = Readonly<\n | {\n type: 'set';\n nextState: S;\n }\n | {\n type: 'update';\n updateFn: (a: S) => S;\n }\n>;\n\nconst reducer = <S,>(state: S, action: Action<S>): S => {\n switch (action.type) {\n case 'set':\n return action.nextState;\n\n case 'update':\n return action.updateFn(state);\n }\n};\n\n/**\n * Creates a reactive state container with getter and setter methods.\n * Provides a simple state management solution with observable state.\n *\n * @template S - The type of the state\n * @param initialState - The initial value of the state\n * @returns A 3-element tuple: `[state, setState, { updateState, resetState, getSnapshot, initialState }]`\n *\n * @example\n * ```ts\n * const [state, setState, { updateState, resetState }] = createState(0);\n *\n * const stateHistory: number[] = [];\n *\n * state.subscribe((value: number) => {\n * stateHistory.push(value);\n * });\n *\n * assert.deepStrictEqual(stateHistory, [0]);\n *\n * setState(10); // logs: 10\n *\n * assert.deepStrictEqual(stateHistory, [0, 10]);\n *\n * updateState((prev: number) => prev + 1); // logs: 11\n *\n * assert.deepStrictEqual(stateHistory, [0, 10, 11]);\n *\n * resetState(); // logs: 0\n *\n * assert.deepStrictEqual(stateHistory, [0, 10, 11, 0]);\n * ```\n */\nexport const createState = <S,>(\n initialState: S,\n): readonly [\n state: InitializedObservable<S>,\n setState: (v: S) => S,\n utils: Readonly<{\n updateState: (updateFn: (prev: S) => S) => S;\n resetState: () => S;\n getSnapshot: () => S;\n initialState: S;\n }>,\n] => {\n const [state, dispatch, { getSnapshot }] = createReducer<S, Action<S>>(\n reducer,\n initialState,\n );\n\n const updateState = (updateFn: (prev: S) => S): S =>\n dispatch({ type: 'update', updateFn });\n\n const setState = (nextState: S): S => dispatch({ type: 'set', nextState });\n\n const resetState = (): S =>\n dispatch({ type: 'set', nextState: initialState });\n\n return [\n state,\n setState,\n {\n updateState,\n resetState,\n getSnapshot,\n initialState,\n },\n ] as const;\n};\n"],"names":[],"mappings":";;AAcA,MAAM,OAAA,GAAU,CAAK,KAAA,EAAU,MAAA,KAAyB;AACtD,EAAA,QAAQ,OAAO,IAAA;AAAM,IACnB,KAAK,KAAA;AACH,MAAA,OAAO,MAAA,CAAO,SAAA;AAAA,IAEhB,KAAK,QAAA;AACH,MAAA,OAAO,MAAA,CAAO,SAAS,KAAK,CAAA;AAAA;AAElC,CAAA;AAmCO,MAAM,WAAA,GAAc,CACzB,YAAA,KAUG;AACH,EAAA,MAAM,CAAC,KAAA,EAAO,QAAA,EAAU,EAAE,WAAA,EAAa,CAAA,GAAI,aAAA;AAAA,IACzC,OAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,MAAM,WAAA,GAAc,CAAC,QAAA,KACnB,QAAA,CAAS,EAAE,IAAA,EAAM,QAAA,EAAU,UAAU,CAAA;AAEvC,EAAA,MAAM,QAAA,GAAW,CAAC,SAAA,KAAoB,QAAA,CAAS,EAAE,IAAA,EAAM,KAAA,EAAO,WAAW,CAAA;AAEzE,EAAA,MAAM,UAAA,GAAa,MACjB,QAAA,CAAS,EAAE,MAAM,KAAA,EAAO,SAAA,EAAW,cAAc,CAAA;AAEnD,EAAA,OAAO;AAAA,IACL,KAAA;AAAA,IACA,QAAA;AAAA,IACA;AAAA,MACE,WAAA;AAAA,MACA,UAAA;AAAA,MACA,WAAA;AAAA,MACA;AAAA;AACF,GACF;AACF;;;;"}
1
+ {"version":3,"file":"create-state.mjs","sourceRoot":"","sources":["../../src/utils/create-state.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAarD,MAAM,OAAO,GAAG,CAAK,KAAQ,EAAE,MAAiB,EAAK,EAAE;IACrD,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,KAAK;YACR,OAAO,MAAM,CAAC,SAAS,CAAC;QAE1B,KAAK,QAAQ;YACX,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC;AACH,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CACzB,YAAe,EAUf,EAAE;IACF,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,WAAW,EAAE,CAAC,GAAG,aAAa,CACtD,OAAO,EACP,YAAY,CACb,CAAC;IAEF,MAAM,WAAW,GAAG,CAAC,QAAwB,EAAK,EAAE,CAClD,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;IAEzC,MAAM,QAAQ,GAAG,CAAC,SAAY,EAAK,EAAE,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IAE3E,MAAM,UAAU,GAAG,GAAM,EAAE,CACzB,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC,CAAC;IAErD,OAAO;QACL,KAAK;QACL,QAAQ;QACR;YACE,WAAW;YACX,UAAU;YACV,WAAW;YACX,YAAY;SACb;KACO,CAAC;AACb,CAAC,CAAC"}
@@ -1,6 +1,6 @@
1
- export { collectToArray } from './collect-to-array.mjs';
2
- export { createBooleanState } from './create-boolean-state.mjs';
3
- export { createEventEmitter, createValueEmitter } from './create-event-emitter.mjs';
4
- export { createReducer } from './create-reducer.mjs';
5
- export { createState } from './create-state.mjs';
6
- //# sourceMappingURL=index.mjs.map
1
+ export * from './collect-to-array.mjs';
2
+ export * from './create-boolean-state.mjs';
3
+ export * from './create-event-emitter.mjs';
4
+ export * from './create-reducer.mjs';
5
+ export * from './create-state.mjs';
6
+ //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
1
+ {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../../src/utils/index.mts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "synstate",
3
- "version": "3.0.0",
3
+ "version": "3.0.2",
4
4
  "description": "Type-safe State Management Library for TypeScript/JavaScript",
5
5
  "repository": {
6
6
  "type": "git",
@@ -29,30 +29,31 @@
29
29
  "LICENSE"
30
30
  ],
31
31
  "dependencies": {
32
- "ts-data-forge": "^14.5.0",
32
+ "ts-data-forge": "^14.7.0",
33
+ "ts-std-forge": "^0.5.0",
33
34
  "ts-type-forge": "^9.2.2"
34
35
  },
35
36
  "devDependencies": {
36
37
  "@reduxjs/toolkit": "2.12.0",
38
+ "@sumi-lang/cli": "0.0.1",
37
39
  "@types/react": "19.2.18",
38
40
  "@vitest/browser-playwright": "4.1.11",
39
- "argparse": "3.0.0",
40
- "eslint-config-typed": "5.10.0",
41
- "eslint-plugin-ts-data-forge": "0.5.1",
42
- "eslint-plugin-ts-fortress": "1.0.5",
43
- "eslint-plugin-ts-type-forge": "0.7.1",
44
- "jotai": "2.20.2",
41
+ "argparse": "3.0.1",
42
+ "eslint-config-typed": "5.11.6",
43
+ "eslint-plugin-ts-data-forge": "0.7.3",
44
+ "eslint-plugin-ts-fortress": "1.2.2",
45
+ "eslint-plugin-ts-type-forge": "0.8.3",
46
+ "jotai": "2.20.3",
45
47
  "mobx": "7.0.3",
46
48
  "playwright": "1.62.1",
47
49
  "prettier": "3.9.6",
48
50
  "prettier-plugin-organize-imports": "4.3.0",
49
51
  "prettier-plugin-packagejson": "3.0.2",
50
52
  "react": "19.2.8",
51
- "rollup": "4.62.4",
52
53
  "rxjs": "7.8.2",
53
- "synstate-react-hooks": "3.0.0",
54
- "synstate-react-hooks-compat": "3.0.0",
55
- "ts-repo-utils": "10.3.2",
54
+ "synstate-react-hooks": "3.0.2",
55
+ "synstate-react-hooks-compat": "3.0.2",
56
+ "ts-repo-utils": "10.6.1",
56
57
  "valtio": "2.3.2",
57
58
  "zustand": "5.0.15"
58
59
  },
@@ -83,6 +84,7 @@
83
84
  "gi:src": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ../../libs/ts-repo-utils/src/cmd/gen-index-ts.mts ./src --index-ext .mts --export-ext .mjs --target-ext .mts --target-ext .tsx --exclude entry-point.mts --exclude \"core/base/**\" --exclude \"core/utils/**\"",
84
85
  "lint": "eslint .",
85
86
  "lint:fix": "eslint . --fix",
87
+ "sumi:check": "tsx --tsconfig ../../tools/configs/tsconfig.tsx.json ../../languages/sumi/cli/src/cmd/sumi.mts check ./tsconfig.sumi.json",
86
88
  "test": "pnpm run z:vitest:node run",
87
89
  "test:browser": "pnpm run z:vitest --project='Browser' run",
88
90
  "test:cov": "pnpm run z:vitest:node run --coverage",
@@ -1,4 +1,5 @@
1
1
  import { Arr, type Optional, type Some } from 'ts-data-forge';
2
+ import { panic } from 'ts-std-forge';
2
3
  import { type MutableSet } from 'ts-type-forge';
3
4
  import {
4
5
  isChildObservable,
@@ -270,7 +271,11 @@ const detectCircularDependency = (
270
271
 
271
272
  for (const parent of parents) {
272
273
  if (hasCircularDependencyFrom(parent, mut_visited, mut_inPath)) {
273
- throw new Error(
274
+ // A programming error (invariant violation), not a recoverable
275
+ // failure. `panic` marks the error it throws, so the `Result` /
276
+ // `AsyncResult` boundaries rethrow it rather than turning an invariant
277
+ // violation into an `Err` a caller might handle (Sumi D-48 / D-53).
278
+ panic(
274
279
  'Circular dependency detected in observable graph: a child observable cannot be its own ancestor.',
275
280
  );
276
281
  }
@@ -1,4 +1,5 @@
1
1
  import { Arr, Optional } from 'ts-data-forge';
2
+ import { unreachable } from 'ts-std-forge';
2
3
  import {
3
4
  type MutableMap,
4
5
  type MutableSet,
@@ -254,7 +255,13 @@ export const createTryUpdateNotImplemented = (): ((
254
255
  ) => void) => tryUpdateNotImplemented;
255
256
 
256
257
  const tryUpdateNotImplemented = (_updateToken: UpdateToken): void => {
257
- throw new Error('not implemented');
258
+ // Not `todo()`: nothing here is waiting to be written. This is the base
259
+ // default of what was a base-class method, and every observable that can
260
+ // receive a parent update supplies its own `tryUpdate`; an observable with
261
+ // no parents never gets one. Reaching this is the invariant breaking, which
262
+ // is what `unreachable` says (Sumi D-48). There is no `never` value to
263
+ // hand it — the fact of the call is the error.
264
+ unreachable();
258
265
  };
259
266
 
260
267
  type AssembleObservableArgs<
@@ -61,10 +61,15 @@ export type ScanOperatorObservable<A, B> = InitializedSyncChildObservable<
61
61
 
62
62
  // SyncChildObservable
63
63
 
64
+ // The helpers stay in a namespace so their names do not crowd the module
65
+ // scope. A namespace holding only types is erasable, so it passes
66
+ // `erasableSyntaxOnly` (TS1294); the `expectType` assertions are call
67
+ // statements, which is why they sit below it rather than beside the types
68
+ // they check.
64
69
  namespace SynStateInternals {
65
70
  type Cast<A> = A extends NonEmptyUnknownList ? A : never;
66
71
 
67
- type EveryInitialized<OS extends NonEmptyTuple<Observable<unknown>>> =
72
+ export type EveryInitialized<OS extends NonEmptyTuple<Observable<unknown>>> =
68
73
  OS extends NonEmptyTuple<InitializedObservable<unknown>> ? true : false;
69
74
 
70
75
  type IsInitialized<O> = readonly [O] extends readonly [
@@ -84,41 +89,9 @@ namespace SynStateInternals {
84
89
  // union distribution
85
90
  LogicalValue<OS extends OS ? IsInitialized<OS> : never>;
86
91
 
87
- type SomeInitialized<OS extends NonEmptyTuple<Observable<unknown>>> =
92
+ export type SomeInitialized<OS extends NonEmptyTuple<Observable<unknown>>> =
88
93
  SomeInitializedImpl<OS[number]>;
89
94
 
90
- expectType<EveryInitialized<readonly [Observable<1>]>, false>('=');
91
-
92
- expectType<EveryInitialized<readonly [InitializedObservable<1>]>, true>('=');
93
-
94
- expectType<
95
- EveryInitialized<
96
- readonly [InitializedObservable<1>, InitializedObservable<2>]
97
- >,
98
- true
99
- >('=');
100
-
101
- expectType<
102
- EveryInitialized<readonly [Observable<1>, InitializedObservable<2>]>,
103
- false
104
- >('=');
105
-
106
- expectType<SomeInitialized<readonly [Observable<1>]>, false>('=');
107
-
108
- expectType<SomeInitialized<readonly [InitializedObservable<1>]>, true>('=');
109
-
110
- expectType<
111
- SomeInitialized<
112
- readonly [InitializedObservable<1>, InitializedObservable<2>]
113
- >,
114
- true
115
- >('=');
116
-
117
- expectType<
118
- SomeInitialized<readonly [Observable<1>, InitializedObservable<2>]>,
119
- true
120
- >('=');
121
-
122
95
  type InitializedCombineObservableImpl<A extends NonEmptyUnknownList> =
123
96
  InitializedSyncChildObservable<A, A>;
124
97
 
@@ -159,6 +132,52 @@ namespace SynStateInternals {
159
132
  : MergeObservableImpl<Unwrap<OS>>;
160
133
  }
161
134
 
135
+ expectType<SynStateInternals.EveryInitialized<readonly [Observable<1>]>, false>(
136
+ '=',
137
+ );
138
+
139
+ expectType<
140
+ SynStateInternals.EveryInitialized<readonly [InitializedObservable<1>]>,
141
+ true
142
+ >('=');
143
+
144
+ expectType<
145
+ SynStateInternals.EveryInitialized<
146
+ readonly [InitializedObservable<1>, InitializedObservable<2>]
147
+ >,
148
+ true
149
+ >('=');
150
+
151
+ expectType<
152
+ SynStateInternals.EveryInitialized<
153
+ readonly [Observable<1>, InitializedObservable<2>]
154
+ >,
155
+ false
156
+ >('=');
157
+
158
+ expectType<SynStateInternals.SomeInitialized<readonly [Observable<1>]>, false>(
159
+ '=',
160
+ );
161
+
162
+ expectType<
163
+ SynStateInternals.SomeInitialized<readonly [InitializedObservable<1>]>,
164
+ true
165
+ >('=');
166
+
167
+ expectType<
168
+ SynStateInternals.SomeInitialized<
169
+ readonly [InitializedObservable<1>, InitializedObservable<2>]
170
+ >,
171
+ true
172
+ >('=');
173
+
174
+ expectType<
175
+ SynStateInternals.SomeInitialized<
176
+ readonly [Observable<1>, InitializedObservable<2>]
177
+ >,
178
+ true
179
+ >('=');
180
+
162
181
  export type CombineObservable<A extends NonEmptyUnknownList> =
163
182
  SynStateInternals.CombineObservableImpl<A>;
164
183
 
@@ -1,2 +1,11 @@
1
- // Timer types for Node.js/Browser compatibility
2
- export type TimerId = ReturnType<typeof setTimeout>;
1
+ /**
2
+ * Timer handle for Node.js / browser compatibility.
3
+ *
4
+ * Defined by what `clearTimeout` accepts rather than by what `setTimeout`
5
+ * returns. The two are not the same type under the strict standard library:
6
+ * `setTimeout` there returns `{} | null`, which `clearTimeout`'s
7
+ * `number | undefined` parameter rejects. Every use of this type here is a
8
+ * handle on its way to `clearTimeout` / `clearInterval`, so the consumer's
9
+ * side is the one that has to fit.
10
+ */
11
+ export type TimerId = NonNullable<Parameters<typeof clearTimeout>[0]>;