@@ -1,4 +1,5 @@
|
|||||||
import { Array, Function, Option, Predicate, Schema } from "effect"
|
import { Array, Function, Option, Predicate, Schema } from "effect"
|
||||||
|
import type { Simplify } from "effect/Types"
|
||||||
|
|
||||||
|
|
||||||
type Prev = readonly [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
type Prev = readonly [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||||
@@ -23,96 +24,36 @@ export type Paths<S, D extends number = 5, Seen = never> = readonly [] | (
|
|||||||
never
|
never
|
||||||
)
|
)
|
||||||
|
|
||||||
export type UnionPaths<Members extends ReadonlyArray<Schema.Schema.All>, D extends number, Seen> = {
|
export type SchemaFromPath<S, P extends readonly any[]> = S extends Schema.Schema.Any
|
||||||
[K in keyof T as K extends number ? K : never]:
|
? P extends [infer Head, ...infer Tail]
|
||||||
| readonly [K]
|
? Head extends keyof S["Type"]
|
||||||
| readonly [K, ...Paths<T[K], Prev[D], Seen>]
|
? (
|
||||||
} extends infer O
|
S extends Schema.TupleType<infer Elements, infer Rest> ? (
|
||||||
? O[keyof O]
|
Head extends keyof Elements ? SchemaFromPath<Elements[Head], Tail> :
|
||||||
: never
|
Head extends keyof Rest ? SchemaFromPath<Rest, Tail> :
|
||||||
|
never
|
||||||
export type ArrayPaths<T extends readonly any[], D extends number, Seen> = {
|
) :
|
||||||
[K in keyof T as K extends number ? K : never]:
|
S extends Schema.Array$<infer Value> ? SchemaFromPath<Value, Tail> :
|
||||||
| readonly [K]
|
S extends Schema.Struct<infer Fields> ? SchemaFromPath<Fields[Head], Tail> :
|
||||||
| readonly [K, ...Paths<T[K], Prev[D], Seen>]
|
never
|
||||||
} extends infer O
|
|
||||||
? O[keyof O]
|
|
||||||
: never
|
|
||||||
|
|
||||||
export type ObjectPaths<T extends object, D extends number, Seen> = {
|
|
||||||
[K in keyof T as K extends string | number | symbol ? K : never]-?:
|
|
||||||
NonNullable<T[K]> extends infer V
|
|
||||||
? readonly [K] | readonly [K, ...Paths<V, Prev[D], Seen>]
|
|
||||||
: never
|
|
||||||
} extends infer O
|
|
||||||
? O[keyof O]
|
|
||||||
: never
|
|
||||||
|
|
||||||
export type ValueFromPath<T, P extends readonly any[]> = P extends [infer Head, ...infer Tail]
|
|
||||||
? Head extends keyof T
|
|
||||||
? ValueFromPath<T[Head], Tail>
|
|
||||||
: T extends readonly any[]
|
|
||||||
? Head extends number
|
|
||||||
? ValueFromPath<T[number], Tail>
|
|
||||||
: never
|
|
||||||
: never
|
|
||||||
: T
|
|
||||||
|
|
||||||
export type AnyPath = readonly PropertyKey[]
|
|
||||||
|
|
||||||
|
|
||||||
export const unsafeGet: {
|
|
||||||
<T, const P extends Paths<T>>(path: P): (self: T) => ValueFromPath<T, P>
|
|
||||||
<T, const P extends Paths<T>>(self: T, path: P): ValueFromPath<T, P>
|
|
||||||
} = Function.dual(2, <T, const P extends Paths<T>>(self: T, path: P): ValueFromPath<T, P> =>
|
|
||||||
path.reduce((acc: any, key: any) => acc?.[key], self)
|
|
||||||
)
|
|
||||||
|
|
||||||
export const get: {
|
|
||||||
<T, const P extends Paths<T>>(path: P): (self: T) => Option.Option<ValueFromPath<T, P>>
|
|
||||||
<T, const P extends Paths<T>>(self: T, path: P): Option.Option<ValueFromPath<T, P>>
|
|
||||||
} = Function.dual(2, <T, const P extends Paths<T>>(self: T, path: P): Option.Option<ValueFromPath<T, P>> =>
|
|
||||||
path.reduce(
|
|
||||||
(acc: Option.Option<any>, key: any): Option.Option<any> => Option.isSome(acc)
|
|
||||||
? Predicate.hasProperty(acc.value, key)
|
|
||||||
? Option.some(acc.value[key])
|
|
||||||
: Option.none()
|
|
||||||
: acc,
|
|
||||||
|
|
||||||
Option.some(self),
|
|
||||||
)
|
)
|
||||||
)
|
: never
|
||||||
|
: S
|
||||||
|
: never
|
||||||
|
|
||||||
export const immutableSet: {
|
const TestSchema = Schema.Struct({
|
||||||
<T, const P extends Paths<T>>(path: P, value: ValueFromPath<T, P>): (self: T) => ValueFromPath<T, P>
|
allUsers: Schema.Array(Schema.Struct({
|
||||||
<T, const P extends Paths<T>>(self: T, path: P, value: ValueFromPath<T, P>): Option.Option<T>
|
name: Schema.String
|
||||||
} = Function.dual(3, <T, const P extends Paths<T>>(self: T, path: P, value: ValueFromPath<T, P>): Option.Option<T> => {
|
})),
|
||||||
const key = Array.head(path as AnyPath)
|
|
||||||
if (Option.isNone(key))
|
|
||||||
return Option.some(value as T)
|
|
||||||
if (!Predicate.hasProperty(self, key.value))
|
|
||||||
return Option.none()
|
|
||||||
|
|
||||||
const child = immutableSet<any, any>(self[key.value], Option.getOrThrow(Array.tail(path as AnyPath)), value)
|
admins: Schema.Tuple(
|
||||||
if (Option.isNone(child))
|
Schema.Struct({
|
||||||
return child
|
name: Schema.Literal("Gneugneu")
|
||||||
|
}),
|
||||||
if (Array.isArray(self))
|
Schema.Struct({
|
||||||
return typeof key.value === "number"
|
name: Schema.Literal("AAAAYA")
|
||||||
? Option.some([
|
}),
|
||||||
...self.slice(0, key.value),
|
),
|
||||||
child.value,
|
|
||||||
...self.slice(key.value + 1),
|
|
||||||
] as T)
|
|
||||||
: Option.none()
|
|
||||||
|
|
||||||
if (typeof self === "object")
|
|
||||||
return Option.some(
|
|
||||||
Object.assign(
|
|
||||||
Object.create(Object.getPrototypeOf(self)),
|
|
||||||
{ ...self, [key.value]: child.value },
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
return Option.none()
|
|
||||||
})
|
})
|
||||||
|
type S = SchemaFromPath<typeof TestSchema, ["admins", 0, "name"]>
|
||||||
|
type T = number extends keyof typeof TestSchema.fields.admins.elements ? true : false
|
||||||
|
|||||||
Reference in New Issue
Block a user