optics-ts icon indicating copy to clipboard operation
optics-ts copied to clipboard

How to traverse `Record` types?

Open cowboyd opened this issue 3 years ago • 7 comments

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?

cowboyd avatar Apr 09 '21 20:04 cowboyd

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?

cowboyd avatar Apr 10 '21 14:04 cowboyd

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

akheron avatar Apr 11 '21 09:04 akheron

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?

cowboyd avatar Apr 11 '21 10:04 cowboyd

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.

cowboyd avatar Apr 11 '21 10:04 cowboyd

How do you type this correctly in TypeScript? I've tried but failed :(

mwisnicki avatar Jul 20 '22 17:07 mwisnicki

I was wondering if there was any movement on implementing the records() traversal?

pkuprys avatar Aug 31 '23 17:08 pkuprys

There's PR #81, but at least back then the TS compiler couldn't typecheck that.

akheron avatar Sep 03 '23 18:09 akheron