[wip] extractProperty proper typing with union types

This commit is contained in:
2025-09-06 17:30:47 -04:00
parent bedafb0b7c
commit b854fec9e5
3 changed files with 17 additions and 32 deletions

View File

@@ -41,33 +41,23 @@ export default (props: { tableKey: string }) => {
ws.on("open", () => res(ws)); ws.on("open", () => res(ws));
ws.on("error", () => res(ws)); ws.on("error", () => res(ws));
}); });
const sendWs = (msg: TWsIn) => wsPromise.then((ws) => ws.send(msg)); const sendWs = (msg: TWsIn) => wsPromise.then((ws) => ws.send(msg));
const wsEvents = fromPromise(wsPromise).flatMap((ws) => const wsEvents = fromPromise(wsPromise).flatMap((ws) =>
fromWebsocket<TWsOut>(ws) fromWebsocket<TWsOut>(ws)
); );
onCleanup(() => wsPromise.then((ws) => ws.close())); onCleanup(() => wsPromise.then((ws) => ws.close()));
const presenceEvents = wsEvents.filter(
(evt) => evt.playersPresent !== undefined
);
const gameConfig = extractProperty(wsEvents, "gameConfig").thru( const gameConfig = extractProperty(wsEvents, "gameConfig").thru(
createObservable createObservable
); );
const view = extractProperty(wsEvents, "view").thru(createObservable);
const gameEvents = wsEvents.filter((evt) => evt.view !== undefined); const players = extractProperty(wsEvents, "playersPresent").thru(
const resultEvents = wsEvents.filter((evt) => evt.results !== undefined); createObservable
const players = createObservableWithInit<string[]>(
presenceEvents.map((evt) => evt.playersPresent!),
[]
); );
const playerNames = createObservableStore( const playerNames = createObservableStore(
wsEvents extractProperty(wsEvents, "playerNames"),
.filter((evt) => evt.playerNames != null)
.map(({ playerNames }) => playerNames!)
.toProperty(),
{} {}
); );
@@ -83,9 +73,6 @@ export default (props: { tableKey: string }) => {
createEffect(() => sendWs({ ready: ready() })); createEffect(() => sendWs({ ready: ready() }));
createEffect(() => sendWs({ name: name() })); createEffect(() => sendWs({ name: name() }));
const viewProp = gameEvents.map((evt) => evt.view).toProperty();
const view = createObservable(viewProp);
return ( return (
<TableContext.Provider <TableContext.Provider

View File

@@ -48,10 +48,8 @@ export const createObservableStore = <T extends object = {}>(
return store; return store;
}; };
export const extractProperty = < type UnionKeys<T> = T extends any ? keyof T : never;
P extends string, export const extractProperty = <T extends object, P extends UnionKeys<T>>(
T extends { [key in P]?: any }
>(
obs: Observable<T, any>, obs: Observable<T, any>,
property: P property: P
): Property<T[P], any> => ): Property<T[P], any> =>

View File

@@ -13,16 +13,16 @@ import { combine, constant, merge, Observable, pool, Property } from "kefir";
import Bus, { type Bus as TBus } from "kefir-bus"; import Bus, { type Bus as TBus } from "kefir-bus";
import { log } from "./logging"; import { log } from "./logging";
export const WsOut = t.Object({ export const WsOut = t.Union([
playersPresent: t.Optional(t.Array(t.String())), t.Object({ playersPresent: t.Array(t.String()) }),
playerNames: t.Optional(t.Record(t.String(), t.String())), t.Object({ playerNames: t.Record(t.String(), t.String()) }),
playersReady: t.Optional(t.Nullable(t.Record(t.String(), t.Boolean()))), t.Object({ playersReady: t.Nullable(t.Record(t.String(), t.Boolean())) }),
gameConfig: t.Optional( t.Object({
t.Object({ game: t.String(), players: t.Array(t.String()) }) gameConfig: t.Object({ game: t.String(), players: t.Array(t.String()) }),
), }),
view: t.Optional(t.Any()), t.Object({ view: t.Any() }),
results: t.Optional(t.Any()), t.Object({ results: t.Any() }),
}); ]);
export type TWsOut = typeof WsOut.static; export type TWsOut = typeof WsOut.static;
export const WsIn = t.Union([ export const WsIn = t.Union([
t.Object({ name: t.String() }), t.Object({ name: t.String() }),