Skip to content

Commit

Permalink
Improve anonymizer return type
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Gudahtt committed Feb 24, 2021
1 parent 9817562 commit 3f41181
Showing 1 changed file with 22 additions and 5 deletions.
27 changes: 22 additions & 5 deletions src/BaseControllerV2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,18 @@ enablePatches();
*/
export type Listener<T> = (state: T, patches: Patch[]) => void;

export type Anonymizer<T> = (value: T) => T;
type Primitive = boolean | string | number | null;

// Based upon this StackOverflow answer: https://stackoverflow.com/a/64060332
type RecursivePartial<T> = {
[P in keyof T]?: T[P] extends (infer U)[]
? RecursivePartial<U>[]
: T[P] extends Primitive
? T[P]
: RecursivePartial<T>;
};

export type Anonymizer<T> = (value: T) => T extends Primitive ? T : RecursivePartial<T>;

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

export function getAnonymizedState<S extends Record<string, any>>(state: S, metadata: StateMetadata<S>) {
export function getAnonymizedState<S extends Record<string, any>>(
state: S,
metadata: StateMetadata<S>,
): RecursivePartial<S> {
return Object.keys(state).reduce((anonymizedState, _key) => {
const key: keyof S = _key; // https://stackoverflow.com/questions/63893394/string-cannot-be-used-to-index-type-t
const metadataValue = metadata[key].anonymous;
Expand All @@ -119,15 +133,18 @@ export function getAnonymizedState<S extends Record<string, any>>(state: S, meta
anonymizedState[key] = state[key];
}
return anonymizedState;
}, {} as Partial<S>);
}, {} as RecursivePartial<S>);
}

export function getPersistentState<S extends Record<string, any>>(state: S, metadata: StateMetadata<S>) {
export function getPersistentState<S extends Record<string, any>>(
state: S,
metadata: StateMetadata<S>,
): RecursivePartial<S> {
return Object.keys(state).reduce((persistedState, _key) => {
const key: keyof S = _key; // https://stackoverflow.com/questions/63893394/string-cannot-be-used-to-index-type-t
if (metadata[key].persist) {
persistedState[key] = state[key];
}
return persistedState;
}, {} as Partial<S>);
}, {} as RecursivePartial<S>);
}

0 comments on commit 3f41181

Please sign in to comment.