|
1 | 1 | import tw from 'twin.macro'; |
2 | | -import create, { StateCreator } from 'zustand'; |
| 2 | +import create, { |
| 3 | + GetState, |
| 4 | + SetState, |
| 5 | + State, |
| 6 | + StateCreator, |
| 7 | + StoreApi, |
| 8 | +} from 'zustand'; |
3 | 9 | import produce from 'immer'; |
| 10 | +import type { Draft } from 'immer'; |
4 | 11 | import { |
5 | 12 | format as d3Format, |
6 | 13 | timeFormat, |
@@ -29,10 +36,34 @@ import { StringFilter } from './components/filters/string'; |
29 | 36 | import { CategoryFilter } from './components/filters/category'; |
30 | 37 | import { RangeFilter } from './components/filters/range'; |
31 | 38 |
|
32 | | -export const immer = <T extends {}>( |
33 | | - config: StateCreator<T, (fn: (draft: T) => void) => void> |
34 | | -): StateCreator<T> => (set, get, api) => |
35 | | - config((fn) => set(produce(fn) as (state: T) => T), get, api); |
| 39 | +const immer = < |
| 40 | + T extends State, |
| 41 | + CustomSetState extends SetState<T>, |
| 42 | + CustomGetState extends GetState<T>, |
| 43 | + CustomStoreApi extends StoreApi<T> |
| 44 | +>( |
| 45 | + config: StateCreator< |
| 46 | + T, |
| 47 | + (partial: ((draft: Draft<T>) => void) | T, replace?: boolean) => void, |
| 48 | + CustomGetState, |
| 49 | + CustomStoreApi |
| 50 | + > |
| 51 | +): StateCreator<T, CustomSetState, CustomGetState, CustomStoreApi> => ( |
| 52 | + set, |
| 53 | + get, |
| 54 | + api |
| 55 | +) => |
| 56 | + config( |
| 57 | + (partial, replace) => { |
| 58 | + const nextState = |
| 59 | + typeof partial === 'function' |
| 60 | + ? produce(partial as (state: Draft<T>) => T) |
| 61 | + : (partial as T); |
| 62 | + return set(nextState, replace); |
| 63 | + }, |
| 64 | + get, |
| 65 | + api |
| 66 | + ); |
36 | 67 |
|
37 | 68 | export type GridState = { |
38 | 69 | data: any[]; |
|
0 commit comments