Skip to content

Commit 3f41181

Browse files
committed
Improve anonymizer return type
The anonymizer function can now return a _recursive partial_ of the input type. So any properties can be omitted in the state property directly or in any nested object. Note that for primitive values and arrays, the return type must still match the state. Similarly, any objects still need to be returned as objects, though they're allowed to have a few less properties.
1 parent 9817562 commit 3f41181

File tree

1 file changed

+22
-5
lines changed

1 file changed

+22
-5
lines changed

src/BaseControllerV2.ts

+22-5
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,18 @@ enablePatches();
1111
*/
1212
export type Listener<T> = (state: T, patches: Patch[]) => void;
1313

14-
export type Anonymizer<T> = (value: T) => T;
14+
type Primitive = boolean | string | number | null;
15+
16+
// Based upon this StackOverflow answer: https://stackoverflow.com/a/64060332
17+
type RecursivePartial<T> = {
18+
[P in keyof T]?: T[P] extends (infer U)[]
19+
? RecursivePartial<U>[]
20+
: T[P] extends Primitive
21+
? T[P]
22+
: RecursivePartial<T>;
23+
};
24+
25+
export type Anonymizer<T> = (value: T) => T extends Primitive ? T : RecursivePartial<T>;
1526

1627
export type StateMetadata<T> = {
1728
[P in keyof T]: {
@@ -109,7 +120,10 @@ function isAnonymizingFunction<T>(x: boolean | Anonymizer<T>): x is Anonymizer<T
109120
return typeof x === 'function';
110121
}
111122

112-
export function getAnonymizedState<S extends Record<string, any>>(state: S, metadata: StateMetadata<S>) {
123+
export function getAnonymizedState<S extends Record<string, any>>(
124+
state: S,
125+
metadata: StateMetadata<S>,
126+
): RecursivePartial<S> {
113127
return Object.keys(state).reduce((anonymizedState, _key) => {
114128
const key: keyof S = _key; // https://stackoverflow.com/questions/63893394/string-cannot-be-used-to-index-type-t
115129
const metadataValue = metadata[key].anonymous;
@@ -119,15 +133,18 @@ export function getAnonymizedState<S extends Record<string, any>>(state: S, meta
119133
anonymizedState[key] = state[key];
120134
}
121135
return anonymizedState;
122-
}, {} as Partial<S>);
136+
}, {} as RecursivePartial<S>);
123137
}
124138

125-
export function getPersistentState<S extends Record<string, any>>(state: S, metadata: StateMetadata<S>) {
139+
export function getPersistentState<S extends Record<string, any>>(
140+
state: S,
141+
metadata: StateMetadata<S>,
142+
): RecursivePartial<S> {
126143
return Object.keys(state).reduce((persistedState, _key) => {
127144
const key: keyof S = _key; // https://stackoverflow.com/questions/63893394/string-cannot-be-used-to-index-type-t
128145
if (metadata[key].persist) {
129146
persistedState[key] = state[key];
130147
}
131148
return persistedState;
132-
}, {} as Partial<S>);
149+
}, {} as RecursivePartial<S>);
133150
}

0 commit comments

Comments
 (0)