parent
b99ac243ab
commit
23ea09ed35
7 changed files with 102 additions and 44 deletions
@ -1,13 +1,46 @@ |
||||
/** |
||||
* Checks whether specified `key` is unset in given object. Always returns |
||||
* `true` when overwrite is allowed. |
||||
*/ |
||||
const checkUnset = <S extends BaseObject>( |
||||
obj: S, |
||||
key: keyof S, |
||||
{ isOverwrite = false }: { isOverwrite?: boolean } = {}, |
||||
): boolean => !(key in obj) || isOverwrite; |
||||
|
||||
const buildObjectStateSetterCallback = |
||||
<S extends Record<string, unknown>>(key: keyof S, value?: S[keyof S]) => |
||||
({ [key]: toReplace, ...restPrevious }: S): S => { |
||||
<S extends BaseObject>( |
||||
key: keyof S, |
||||
value?: S[keyof S], |
||||
{ |
||||
guard, |
||||
set = (o, k, v) => { |
||||
if (v !== undefined) { |
||||
o[k] = v; |
||||
} |
||||
}, |
||||
}: BuildObjectStateSetterCallbackOptions<S> = {}, |
||||
): BuildObjectStateSetterCallbackReturnType<S> => |
||||
(previous: S): S => { |
||||
const { [key]: toReplace, ...restPrevious } = previous; |
||||
const result = { ...restPrevious } as S; |
||||
|
||||
if (value !== undefined) { |
||||
result[key] = value; |
||||
if (guard?.call(null, previous, key, value)) { |
||||
set(result, key, value); |
||||
} |
||||
|
||||
return result; |
||||
}; |
||||
|
||||
export const buildProtectedObjectStateSetterCallback = <S extends BaseObject>( |
||||
key: keyof S, |
||||
value?: S[keyof S], |
||||
{ |
||||
isOverwrite, |
||||
guard = (o, k) => checkUnset(o, k, { isOverwrite }), |
||||
set, |
||||
}: BuildObjectStateSetterCallbackOptions<S> = {}, |
||||
): BuildObjectStateSetterCallbackReturnType<S> => |
||||
buildObjectStateSetterCallback(key, value, { isOverwrite, guard, set }); |
||||
|
||||
export default buildObjectStateSetterCallback; |
||||
|
@ -0,0 +1,23 @@ |
||||
type BaseObject<T = unknown> = Record<number | string | symbol, T>; |
||||
|
||||
type ObjectStatePropGuard<S extends BaseObject> = ( |
||||
previous: S, |
||||
key: keyof S, |
||||
value?: S[keyof S], |
||||
) => boolean; |
||||
|
||||
type ObjectStatePropSetter<S extends BaseObject> = ( |
||||
result: S, |
||||
key: keyof S, |
||||
value?: S[keyof S], |
||||
) => void; |
||||
|
||||
type BuildObjectStateSetterCallbackOptions<S extends BaseObject> = { |
||||
guard?: ObjectStatePropGuard<S>; |
||||
isOverwrite?: boolean; |
||||
set?: ObjectStatePropSetter<S>; |
||||
}; |
||||
|
||||
type BuildObjectStateSetterCallbackReturnType<S extends BaseObject> = ( |
||||
previous: S, |
||||
) => S; |
Loading…
Reference in new issue