capi
capi copied to clipboard
`Rune.spread` util for convenient merging of tuple/object runes
Let's say we have the following:
const a = Rune.constant(["a", "b", "c"])
const b = Rune.constant(["d", "e", "f"])
A Rune.spread util could be used as follows.
const merged = Rune.spread(a, b)
Instead of...
const merged = Rune
.tuple([a, b])
.map(([a, b]) => [...a, ...b])
(there would have to be two different functions, one for arrays and one for objects; JS distinguishes them by syntax, but we haven't such a luxury here)
Would it be possible for us to boil this into Rune.array, Rune.tuple and Rune.rec without too wild of typings? Aka.
const a = Rune.constant(["a", "b", "c"])
const b = Rune.constant(["d", "e", "f"])
const merged = Rune.tuple(a, b, ["g", "h"], Rune.constant(["i", "j"]))
The typings would probably be fairly hairy, and it would make the error of Rune.tuple("a", "b") much more confusing.
Having to tuple/record/array-ify some values in order to map them into their merged counterpart is... a lot.
Is there another approach that would offer the same usability gain?
I'll play with the API and see what seems most ergonomic
How about a .spread property? That way we can use spread in any position like in vanilla TS
For tuples:
const a = Rune.tuple(["a", "b", "c"])
const b = Rune.tuple(["d", "e", "f"])
// merged: Rune<["a", "b", "c", 1, 2, 3, "d", "e", "f"], never>
const merged = Rune.tuple([a.spread, 1, 2, 3, b.spread])
For a simple array, I think it'd be easier to add the concat method to Array rune.
const a = Rune.array(["a", "b", "c"])
const b = Rune.array(["d", "e", "f"])
const merged = a.into(ArrayRune).concat(b)
Additionally, we could add a merge method for arrays and objects on something like ValueRune.
const a = Rune.constant(["a", "b", "c"])
const b = Rune.constant(["d", "e", "f"])
const merged = Rune.merge(a, b)
const c = Rune.constant({ hello: "world" })
const d = Rune.constant({ hello1: "world1" })
const merged = Rune.merge(a, b)
Not sure where to keep this last one though, it could be on Rune.merge or ValueRune.merge (not static) or ArrayRune.concat. I think it's worth it to think about where we should handle common behavior amongst Rune, ValueRune, ArrayRune, Rune.tuple and etc.
Regarding this...
const merged = Rune.tuple([a.spread, 1, 2, 3, b.spread])
... it has the same problem as one of the aforementioned designs: in T6's words:
The typings would probably be fairly hairy
Each factory's types (tuple, array, rec) would become far more complicated.
Regarding this approach...
const a = Rune.array(["a", "b", "c"])
const b = Rune.array(["d", "e", "f"])
const merged = a.into(ArrayRune).concat(b)
... this might be nice. One other idea:
Rune.spread(Rune.tuple, [[], [], []])
Rune.spread(Rune.rec, [{}, {}, {}])