From 140c88a65c77959bd2217163382653956890f3d6 Mon Sep 17 00:00:00 2001 From: cynecx Date: Sat, 19 Jun 2021 01:58:56 +0200 Subject: [PATCH] improve typings for state setter by utilizing readonly --- packages/solid/src/reactive/state.ts | 25 +++++++++++++++-- packages/solid/src/reactive/stateModifiers.ts | 27 ++++++++++++++----- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/packages/solid/src/reactive/state.ts b/packages/solid/src/reactive/state.ts index a7c181cb0..239e6573b 100644 --- a/packages/solid/src/reactive/state.ts +++ b/packages/solid/src/reactive/state.ts @@ -228,12 +228,33 @@ export function updatePath(current: StateNode, path: any[], traversed: (number | } else setProperty(current, part, value); } +export declare type Readonly = { readonly [K in keyof T]: DeepReadonly }; +export declare type DeepReadonly = T extends [infer A] + ? Readonly<[A]> + : T extends [infer A, infer B] + ? Readonly<[A, B]> + : T extends [infer A, infer B, infer C] + ? Readonly<[A, B, C]> + : T extends [infer A, infer B, infer C, infer D] + ? Readonly<[A, B, C, D]> + : T extends [infer A, infer B, infer C, infer D, infer E] + ? Readonly<[A, B, C, D, E]> + : T extends [infer A, infer B, infer C, infer D, infer E, infer F] + ? Readonly<[A, B, C, D, E, F]> + : T extends [infer A, infer B, infer C, infer D, infer E, infer F, infer G] + ? Readonly<[A, B, C, D, E, F, G]> + : T extends [infer A, infer B, infer C, infer D, infer E, infer F, infer G, infer H] + ? Readonly<[A, B, C, D, E, F, G, H]> + : T extends object + ? Readonly + : T; + export type StateSetter = | Partial | (( - prevState: T extends NotWrappable ? T : State, + prevState: T extends NotWrappable ? T : State>, traversed?: (string | number)[] - ) => Partial | void); + ) => Partial> | void); export type StatePathRange = { from?: number; to?: number; by?: number }; export type ArrayFilterFn = ( diff --git a/packages/solid/src/reactive/stateModifiers.ts b/packages/solid/src/reactive/stateModifiers.ts index 430d26e39..ccdac3c5c 100644 --- a/packages/solid/src/reactive/stateModifiers.ts +++ b/packages/solid/src/reactive/stateModifiers.ts @@ -1,4 +1,13 @@ -import { setProperty, unwrap, isWrappable, State, NotWrappable, StateNode, $RAW } from "./state"; +import { + setProperty, + unwrap, + isWrappable, + State, + NotWrappable, + StateNode, + DeepReadonly, + $RAW, +} from "./state"; export type ReconcileOptions = { key?: string | null; @@ -106,10 +115,13 @@ function applyState( export function reconcile( value: T | State, options: ReconcileOptions = {} -): (state: T extends NotWrappable ? T : State) => T extends NotWrappable ? T : State { +): ( + state: T extends NotWrappable ? T : State> +) => T extends NotWrappable ? T : State { const { merge, key = "id" } = options, v = unwrap(value); - return state => { + return s => { + const state = s as T extends NotWrappable ? T : State; if (!isWrappable(state) || !isWrappable(v)) return v as T extends NotWrappable ? T : State; applyState(v, { state }, "state", merge, key); return state; @@ -137,9 +149,12 @@ const setterTraps: ProxyHandler = { // Immer style mutation style export function produce( fn: (state: T) => void -): (state: T extends NotWrappable ? T : State) => T extends NotWrappable ? T : State { - return state => { - if (isWrappable(state)) fn((new Proxy(state as object, setterTraps) as unknown) as T); +): ( + state: T extends NotWrappable ? T : State> +) => T extends NotWrappable ? T : State { + return s => { + const state = s as T extends NotWrappable ? T : State; + if (isWrappable(state)) fn(new Proxy(state as object, setterTraps) as unknown as T); return state; }; }