diff --git a/packages/reffuse/src/types/PropertyPath.ts b/packages/reffuse/src/types/PropertyPath.ts index 8c1655d..5806f4e 100644 --- a/packages/reffuse/src/types/PropertyPath.ts +++ b/packages/reffuse/src/types/PropertyPath.ts @@ -1,4 +1,4 @@ -import { Array, Option, Predicate } from "effect" +import { Array, Function, Option, Predicate } from "effect" export type Paths = [] | ( @@ -37,57 +37,58 @@ export type AnyKey = string | number | symbol export type AnyPath = readonly AnyKey[] -export const unsafeGet = >( - parent: T, - path: P, -): ValueFromPath => ( - path.reduce((acc: any, key: any) => acc?.[key], parent) +export const unsafeGet: { + >(path: P): (self: T) => ValueFromPath + >(self: T, path: P): ValueFromPath +} = Function.dual(2, >(self: T, path: P): ValueFromPath => + path.reduce((acc: any, key: any) => acc?.[key], self) ) -export const get = >( - parent: T, - path: P, -): Option.Option> => path.reduce( - (acc: Option.Option, key: any): Option.Option => Option.isSome(acc) - ? Predicate.hasProperty(acc.value, key) - ? Option.some(acc.value[key]) - : Option.none() - : acc, +export const get: { + >(path: P): (self: T) => Option.Option> + >(self: T, path: P): Option.Option> +} = Function.dual(2, >(self: T, path: P): Option.Option> => + path.reduce( + (acc: Option.Option, key: any): Option.Option => Option.isSome(acc) + ? Predicate.hasProperty(acc.value, key) + ? Option.some(acc.value[key]) + : Option.none() + : acc, - Option.some(parent), + Option.some(self), + ) ) -export const immutableSet = >( - parent: T, - path: P, - value: ValueFromPath, -): Option.Option => { +export const immutableSet: { + >(path: P, value: ValueFromPath): (self: T) => ValueFromPath + >(self: T, path: P, value: ValueFromPath): Option.Option +} = Function.dual(3, >(self: T, path: P, value: ValueFromPath): Option.Option => { const key = Array.head(path as AnyPath) if (Option.isNone(key)) return Option.some(value as T) - if (!Predicate.hasProperty(parent, key.value)) + if (!Predicate.hasProperty(self, key.value)) return Option.none() - const child = immutableSet(parent[key.value], Option.getOrThrow(Array.tail(path as AnyPath)), value) + const child = immutableSet(self[key.value], Option.getOrThrow(Array.tail(path as AnyPath)), value) if (Option.isNone(child)) return child - if (Array.isArray(parent)) + if (Array.isArray(self)) return typeof key.value === "number" ? Option.some([ - ...parent.slice(0, key.value), + ...self.slice(0, key.value), child.value, - ...parent.slice(key.value + 1), + ...self.slice(key.value + 1), ] as T) : Option.none() - if (typeof parent === "object") + if (typeof self === "object") return Option.some( Object.assign( - Object.create(Object.getPrototypeOf(parent)), - { ...parent, [key.value]: child.value }, + Object.create(Object.getPrototypeOf(self)), + { ...self, [key.value]: child.value }, ) ) return Option.none() -} +})