.derive(get, set): Optic
tsOptic<A>.derive: <B>(selector: { get: (a: A) => B }) => Optic<B, readOnly>;Optic<A>.derive: <B>(lens: { get: (a: A) => B, set: (b: B, a: A) => A }) => Optic<B>;
tsOptic<A>.derive: <B>(selector: { get: (a: A) => B }) => Optic<B, readOnly>;Optic<A>.derive: <B>(lens: { get: (a: A) => B, set: (b: B, a: A) => A }) => Optic<B>;
The derive method allows you to derive a new optic from the current one with a custom get and set function.
- The 
getfunction is a simple selector, returning a new value derived from what the current optic is focused on. - The 
setfunction lets you specify how to update the original value when the derived one is updated. It is optional, if you don't pass it the method returns a read-only Optic. 
tip
The get function is memoized for you, it will only run when the original value changes.
Examples:
tsconstmillisecondsOptic =createState (15_000);constsecondsOptic =millisecondsOptic .derive ({get : (ms ) =>ms / 1000,set : (seconds ) =>seconds * 1000,});
tsconstmillisecondsOptic =createState (15_000);constsecondsOptic =millisecondsOptic .derive ({get : (ms ) =>ms / 1000,set : (seconds ) =>seconds * 1000,});
Here our secondsOptic optic allows us to read and manipulate our time measurement in seconds even though it is represented in milliseconds in our state.
tssecondsOptic .get (); // 15// make it on minutesecondsOptic .set (60);millisecondsOptic .get (); // 60_000
tssecondsOptic .get (); // 15// make it on minutesecondsOptic .set (60);millisecondsOptic .get (); // 60_000
If you don't pass a set function you get a read-only Optic:
tsconstsecondsOptic =millisecondsOptic .derive ({get : (ms ) =>ms / 1000 });
tsconstsecondsOptic =millisecondsOptic .derive ({get : (ms ) =>ms / 1000 });
- The derived type can be different from the original type:
 
tsconstobjectOptic =createState ({firstName : "Aaron",lastName : "Schwartz" });consttupleOptic =objectOptic .derive ({get : ({firstName ,lastName }) => [firstName ,lastName ] asconst ,set : ([firstName ,lastName ]) => ({firstName ,lastName }),});// The original optic is focused on an object while the derived optic is focused on a tuple
tsconstobjectOptic =createState ({firstName : "Aaron",lastName : "Schwartz" });consttupleOptic =objectOptic .derive ({get : ({firstName ,lastName }) => [firstName ,lastName ] asconst ,set : ([firstName ,lastName ]) => ({firstName ,lastName }),});// The original optic is focused on an object while the derived optic is focused on a tuple
- Here's how we would focus on an object's property with 
derive, if it wasn't already built-in: 
tsconstpersonOptic =createState ({firstName : "Aaron",lastName : "Schwartz" });constlastNameOptic =personOptic .derive ({get : (person ) =>person .lastName ,set : (lastName ,person ) => ({ ...person ,lastName }),});
tsconstpersonOptic =createState ({firstName : "Aaron",lastName : "Schwartz" });constlastNameOptic =personOptic .derive ({get : (person ) =>person .lastName ,set : (lastName ,person ) => ({ ...person ,lastName }),});
info
Lawful optics
For your new optic to make sense the following laws must be respected.
Where a is the original value and b is the derived one:
get(set(b, a)) == b
(Ensures that when you set a value, you always get the same value back)set(get(a), a) == a
(Ensures that when you get a value and set it back, the original value doesn't change)