@effect-ts/system
Version:
Effect-TS is a zero dependency set of libraries to write highly productive, purely functional TypeScript at scale.
114 lines (96 loc) • 2.61 kB
text/typescript
// ets_tracing: off
import type { Has, Tag } from "../Has/index.js"
import type { Async } from "./core.js"
import * as has from "./has.js"
export type ShapeFn<T> = Pick<
T,
{
[k in keyof T]: T[k] extends (
...args: infer ARGS
) => Async<infer R, infer E, infer A>
? ((...args: ARGS) => Async<R, E, A>) extends T[k]
? k
: never
: never
}[keyof T]
>
export type ShapeCn<T> = Pick<
T,
{
[k in keyof T]: T[k] extends Async<any, any, any> ? k : never
}[keyof T]
>
export type DerivedLifted<
T,
Fns extends keyof ShapeFn<T>,
Cns extends keyof ShapeCn<T>,
Values extends keyof T
> = {
[k in Fns]: T[k] extends (...args: infer ARGS) => Async<infer R, infer E, infer A>
? (...args: ARGS) => Async<R & Has<T>, E, A>
: never
} & {
[k in Cns]: T[k] extends Async<infer R, infer E, infer A>
? Async<R & Has<T>, E, A>
: never
} & {
[k in Values]: Async<Has<T>, never, T[k]>
}
export function deriveLifted<T>(
H: Tag<T>
): <
Fns extends keyof ShapeFn<T> = never,
Cns extends keyof ShapeCn<T> = never,
Values extends keyof T = never
>(
functions: Fns[],
effects: Cns[],
values: Values[]
) => DerivedLifted<T, Fns, Cns, Values> {
return (functions, constants, values) => {
const ret = {} as any
for (const k of functions) {
// @ts-expect-error
ret[k] = (...args: any[]) => has.accessServiceM(H)((h) => h[k](...args))
}
for (const k of constants) {
// @ts-expect-error
ret[k] = has.accessServiceM(H)((h) => h[k])
}
for (const k of values) {
ret[k] = has.accessService(H)((h) => h[k])
}
return ret as any
}
}
export type DerivedAccessM<T, Gens extends keyof T> = {
[k in Gens]: <R_, E_, A_>(
f: (_: T[k]) => Async<R_, E_, A_>,
__trace?: string
) => Async<R_ & Has<T>, E_, A_>
}
export function deriveAccessM<T>(
H: Tag<T>
): <Gens extends keyof T = never>(generics: Gens[]) => DerivedAccessM<T, Gens> {
return (generics) => {
const ret = {} as any
for (const k of generics) {
ret[k] = (f: any) => has.accessServiceM(H)((h) => f(h[k]))
}
return ret as any
}
}
export type DerivedAccess<T, Gens extends keyof T> = {
[k in Gens]: <A_>(f: (_: T[k]) => A_, __trace?: string) => Async<Has<T>, never, A_>
}
export function deriveAccess<T>(
H: Tag<T>
): <Gens extends keyof T = never>(generics: Gens[]) => DerivedAccess<T, Gens> {
return (generics) => {
const ret = {} as any
for (const k of generics) {
ret[k] = (f: any) => has.accessService(H)((h) => f(h[k]))
}
return ret as any
}
}