optics-ts
optics-ts copied to clipboard
How to traverse `Record` types?
Is there the equivalent of the array value elems()
traversal for Record values? I'm thinking things like keys()
, values()
, and entries()
.
Also, if you want to compose optics that are not included in the builder syntax is there an "escape hatch"? In other words, how would I define a values()
traversal in user-land that didn't require a change to optics-ts itself?
Ok, I think this is at least one answer to my own question.
You can make the entries traversal by composing a object -> entries iso with the elems traversal. keys
and values
are just a simple composition of nth()
with the entries.
import { optic } from 'optic-ts';
let entries = optic()
.iso(
(o) => Object.entries(o),
(entries) => entries.reduce(
(o, [k, v]) => Object.assign(o, { [k]: v })
, {}))
.elems()
let keys = entries.nth(0)
let values = entries.nth(1)
Wow, that felt great! I think this is the first optics library where I was actually able to figure it out on my own. Congratulations on making a really nice API.
Have you considered adding an entries
traversal or iso like the above to the Optic
builder interface?
Nice! I can add the record traversals.
I don’t think there’s a way to amend the interface with new optics. However, I’m working on a new API in which optics are just functions or values instead of object methods. There you could just create new optics and use them without having to worry about any builders.
Here’s one example usage of the new API: https://github.com/akheron/optics-ts/blob/floating/src/floating/valueOr.spec.ts#L8
I'll have a look. I was playing around with them and I did tweak the entries()
iso just a bit to support removing a specific value or key by only reconstructing the entry if it has two elements.
Here's the playground I was working with if it helps https://runkit.com/cowboyd/optics-ts-record-traversal
When do you think the new API will come out?
Also, fwiw, I don't mind the builder syntax so much since you've included top-level functions to use once you've constructed the lens.
How do you type this correctly in TypeScript? I've tried but failed :(
I was wondering if there was any movement on implementing the records() traversal?
There's PR #81, but at least back then the TS compiler couldn't typecheck that.