diff --git a/src/focusAtom.ts b/src/focusAtom.ts index df6f17f..f80dee5 100644 --- a/src/focusAtom.ts +++ b/src/focusAtom.ts @@ -17,6 +17,14 @@ const isFunction = (x: T): x is T & ((...args: any[]) => any) => type NonFunction = [T] extends [(...args: any[]) => any] ? never : T; +type LensLike = + | O.Lens + | O.Equivalence + | O.Iso + | O.Prism + | O.Traversal + | O.Setter; + // Pattern 1: Promise export function focusAtom( @@ -36,6 +44,11 @@ export function focusAtom( ) => O.Lens | O.Equivalence | O.Iso, ): WritableAtom, [SetStateAction], R>; +export function focusAtom( + baseAtom: WritableAtom, [Promise], R>, + callback: (optic: O.OpticFor_) => O.Setter, +): WritableAtom, [NonFunction], R>; + // Pattern 2: Promise with undefined type export function focusAtom( @@ -55,6 +68,11 @@ export function focusAtom( ) => O.Lens | O.Equivalence | O.Iso, ): WritableAtom, [SetStateAction], R>; +export function focusAtom( + baseAtom: WritableAtom, [Promise], R>, + callback: (optic: O.OpticFor_) => O.Setter, +): WritableAtom, [NonFunction], R>; + // Pattern 3: Default export function focusAtom( @@ -74,6 +92,11 @@ export function focusAtom( ) => O.Lens | O.Equivalence | O.Iso, ): WritableAtom], R>; +export function focusAtom( + baseAtom: WritableAtom], R>, + callback: (optic: O.OpticFor_) => O.Setter, +): WritableAtom], R>; + // Pattern 4: Default with undefined type export function focusAtom( @@ -93,18 +116,16 @@ export function focusAtom( ) => O.Lens | O.Equivalence | O.Iso, ): WritableAtom], R>; +export function focusAtom( + baseAtom: WritableAtom], R>, + callback: (optic: O.OpticFor_) => O.Setter, +): WritableAtom], R>; + // Implementation export function focusAtom( baseAtom: WritableAtom], R>, - callback: ( - optic: O.OpticFor_, - ) => - | O.Lens - | O.Equivalence - | O.Iso - | O.Prism - | O.Traversal, + callback: (optic: O.OpticFor_) => LensLike, ) { return memo2( () => { @@ -118,7 +139,9 @@ export function focusAtom( }, (get, set, update: SetStateAction) => { const newValueProducer = isFunction(update) - ? O.modify(focus)(update) + ? O.modify(focus as Exclude, O.Setter>)( + update, + ) : O.set(focus)(update); const base = get(baseAtom); return set( @@ -136,15 +159,7 @@ export function focusAtom( ); } -const getValueUsingOptic = ( - focus: - | O.Lens - | O.Equivalence - | O.Iso - | O.Prism - | O.Traversal, - bigValue: S, -) => { +const getValueUsingOptic = (focus: LensLike, bigValue: S) => { if (focus._tag === 'Traversal') { const values = O.collect(focus)(bigValue); return values; @@ -153,6 +168,9 @@ const getValueUsingOptic = ( const value = O.preview(focus)(bigValue); return value; } + if (focus._tag === 'Setter') { + return undefined; + } const value = O.get(focus)(bigValue); return value; };