1- import { Keyof as K } from "./util.ts" ;
1+ export type Subscriber < T > = ( value : T ) => void ;
22
3- type StateEntries < Obj extends Record < string , State > > = { [ k in K < Obj > ] : { key : k ; value : Obj [ k ] [ "value" ] } } [ K < Obj > ] ;
4- type MapEntries < Rs extends State [ ] > = { [ k in keyof Rs ] : { key : k ; value : Rs [ k ] [ "value" ] } } [ number ] ;
5-
6- export type Subscriber < T > = ( value : T , unused ?: unknown ) => void ;
7- export type KeyedSubscriber < K extends { key : unknown ; value : unknown } > = ( value : K [ "value" ] , key : K [ "key" ] ) => void ;
8- export type StateType < R extends State > = R extends State < infer U > ? U : never ;
3+ type MergedStateValue < Obj extends Record < string , State > > = {
4+ [ key in keyof Obj ] : [ key : key , value : Obj [ key ] [ "value" ] ] ;
5+ } [ keyof Obj ] ;
96
107export class ReadonlyState < T = any > {
118 protected subscribers : Subscriber < T > [ ] = [ ] ;
9+ #state: { value : T } ;
10+
11+ constructor ( state : { value : T } ) {
12+ this . #state = state ;
13+ }
1214
13- constructor ( public value : T ) { }
15+ get value ( ) : T {
16+ return this . #state. value ;
17+ }
1418
1519 static isState < X > ( x : X ) : x is Extract < X , State | ReadonlyState > {
1620 return x instanceof ReadonlyState ;
@@ -34,59 +38,48 @@ export class ReadonlyState<T = any> {
3438}
3539
3640export class State < T = any > extends ReadonlyState < T > {
41+ #state: { value : T } ;
42+
3743 constructor ( value : T ) {
38- super ( value ) ;
44+ const state = { value } ;
45+ super ( state ) ;
46+ this . #state = state ;
3947 }
4048
4149 /**
4250 * Merge multiple states into a single state
4351 */
44- static merge < T > ( ...states : [ State < T > , ...State < T > [ ] ] ) : MergedState < MapEntries < State < T > [ ] > > ;
52+ static merge < T > ( ...states : [ State < T > , ...State < T > [ ] ] ) : State < [ number , T ] > ;
4553
46- static merge < RefMap extends { [ k : string ] : State } > ( refs : RefMap ) : MergedState < StateEntries < RefMap > > ;
54+ static merge < RefMap extends { [ k : string ] : State } > ( refs : RefMap ) : State < MergedStateValue < RefMap > > ;
4755
4856 static merge < T , RefMap extends { [ k : string ] : State } > (
49- ...refs : [ State < T > | RefMap , ...State < T > [ ] ]
50- ) : State < T > | MergedState < MapEntries < State < T > [ ] > > | MergedState < StateEntries < RefMap > > {
51- if ( State . isState ( refs [ 0 ] ) ) {
52- const ref = new MergedState < MapEntries < State < T > [ ] > > ( refs [ 0 ] . value ) ;
53- for ( let i = 0 ; i < refs . length ; i ++ ) {
54- const r = refs [ i ] as State < T > ;
55- r . listen ( x => ref . publish ( x , i ) ) ;
57+ ...states : [ State < T > | RefMap , ...State < T > [ ] ]
58+ ) : State < T > | State < [ number , T ] > | State < MergedStateValue < RefMap > > {
59+ if ( State . isState ( states [ 0 ] ) ) {
60+ const merged = new State < [ number , T ] > ( [ 0 , states [ 0 ] . value ] ) ;
61+ for ( let index = 0 ; index < states . length ; index ++ ) {
62+ const state = states [ index ] as State < T > ;
63+ state . listen ( updated => merged . publish ( [ index , updated ] ) ) ;
5664 }
57- return ref ;
65+ return merged ;
5866 } else {
59- const ref = new MergedState < StateEntries < RefMap > > ( null ) ;
60- const rs = refs [ 0 ] ;
61- for ( const r in rs ) rs [ r ] . listen ( c => ref . publish ( c , r ) ) ;
62- return ref ;
67+ const obj = states [ 0 ] ;
68+ type MergedValue = MergedStateValue < RefMap > ;
69+ const merged = new State < MergedValue > ( Object . values ( obj ) [ 0 ] ?. value ) ;
70+ for ( const key in obj ) obj [ key ] . listen ( updated => merged . publish ( [ key , updated ] ) ) ;
71+ return merged ;
6372 }
6473 }
6574
66- publish ( next : T | Promise < T > , unused ?: unknown ) {
75+ publish ( next : T | Promise < T > ) {
6776 return Promise . resolve ( next ) . then ( val => {
68- this . value = val ;
77+ this . #state . value = val ;
6978 this . subscribers . forEach ( subscriber => subscriber ( val ) ) ;
7079 } ) ;
7180 }
7281
7382 readonly ( ) {
74- return new ReadonlyState ( this . value ) ;
75- }
76- }
77-
78- export class MergedState < T extends { key : string | number ; value : unknown } > extends State < T [ "value" ] > {
79- // @ts -expect-error
80- protected subscribers : KeyedSubscriber < T > [ ] ;
81-
82- listen ( listener : KeyedSubscriber < T > ) : void {
83- this . subscribers . push ( listener ) ;
84- }
85-
86- publish ( value : T [ "value" ] | Promise < T [ "value" ] > , key : T [ "key" ] ) {
87- return Promise . resolve ( value ) . then ( val => {
88- this . value = val ;
89- this . subscribers . forEach ( subscriber => subscriber ( val , key ) ) ;
90- } ) ;
83+ return new ReadonlyState ( this . #state) ;
9184 }
9285}
0 commit comments