ServiceOf<S, Self>The full service interface inferred from a Spec. Wire Methods map to
Effect/function members; off-wire LocalMethods surface as
Effect<T, never, Local<Self>> — yield* to obtain the value, requiring the local layer
(Local) (so they're uncallable through Hyperlink.client).
export type type ServiceOf<S extends Spec, Self = unknown> = { [K in keyof { readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends {
readonly _tag: "constant";
} ? SuccessOf<AsMethod<S[K]>> : S[K] extends {
readonly _tag: "ref";
} ? Subscribable<SuccessOf<AsMethod<S[K]>>> : S[K] extends {
readonly kind: MethodKind;
} ? ClientMethod<...> : S[K] extends Spec ? Simplify<...> : never; }]: { readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends {
readonly _tag: "constant";
} ? SuccessOf<AsMethod<S[K]>> : S[K] extends {
readonly _tag: "ref";
} ? Subscribable<SuccessOf<AsMethod<S[K]>>> : S[K] extends {
readonly kind: MethodKind;
} ? ClientMethod<...> : S[K] extends Spec ? Simplify<...> : never; }[K]; } extends infer B ? B : never
The full service interface inferred from a
Spec
. Wire
Method
s map to
Effect/function members; off-wire
LocalMethod
s surface as
Effect<T, never, Local<Self>> — yield* to obtain the value, requiring the local layer
(
Local
) (so they're uncallable through
Hyperlink.client
).
ServiceOf<function (type parameter) S in type ServiceOf<S extends Spec, Self = unknown>S extends Spec, function (type parameter) Self in type ServiceOf<S extends Spec, Self = unknown>Self = unknown> = type Simplify<A> = { [K in keyof A]: A[K]; } extends infer B ? B : neverFlattens an intersection type into a single object type for readability.
When to use
Use to clean up IDE tooltips that show A & B & C instead of a merged
object.
Details
Does not change the type semantically, only its display.
Example (Simplifying an intersection)
import type { Types } from "effect"
// Without Simplify: IDE shows { a: number } & { b: string }
// With Simplify: IDE shows { a: number; b: string }
type Clean = Types.Simplify<{ a: number } & { b: string }>
Simplify<{
readonly [function (type parameter) KK in keyof function (type parameter) S in type ServiceOf<S extends Spec, Self = unknown>S]: function (type parameter) S in type ServiceOf<S extends Spec, Self = unknown>S[function (type parameter) KK] extends interface FromLocalMethod<M>A
fromService
local member as it sits in the resolved spec: a
LocalMethod
that
additionally carries the service interface's member type M, so
ServiceOf
surfaces it via
InjectLocal
(its own Effect/function + Local) instead of the value-obtain
LocalEffect
a plain local<T>() gets. Type-only; at runtime it's an ordinary bare
local
.
FromLocalMethod<infer function (type parameter) MM>
? type InjectLocal<T, Self> = T extends Effect.Effect<infer A, infer E, infer R> ? Effect.Effect<A, E, R | Local<Self>> : T extends Stream.Stream<infer A, infer E, infer R> ? Stream.Stream<A, E, Local<Self> | R> : T extends (...args: infer Args) => Effect.Effect<infer A, infer E, infer R> ? (...args: Args) => Effect.Effect<A, E, R | Local<Self>> : T extends (...args: infer Args) => Stream.Stream<infer A, infer E, infer R> ? (...args: Args) => Stream.Stream<A, E, R | Local<Self>> : Effect.Effect<...>Inject the
Local
capability into a service member's requirement channel — how a
fromService
local member surfaces. An Effect/Stream-returning member (or a function to
one) keeps its shape and gains Local<Self> in its requirements; any other value is obtained via
Effect<T, never, Local<Self>>. Regular (local) layers satisfy Local; a client layer can't, so
calling a local on a client is a compile error.
InjectLocal<function (type parameter) MM, function (type parameter) Self in type ServiceOf<S extends Spec, Self = unknown>Self> // fromService local: interface-shaped, gains `Local`
: function (type parameter) S in type ServiceOf<S extends Spec, Self = unknown>S[function (type parameter) KK] extends interface LocalMethod<T>A local-only member of a resource contract — built by
Hyperlink.local
. It is
not part of the wire contract (no schema, no rpc): use it for things that can't cross
RPC simply (a returned function, a raw Fiber/Scope/Ref, a callback). Its declared
type T is given directly. In the service it surfaces as
Effect<T, never, Local<Self>> — you yield* it to obtain the value, which requires the
local layer (
Local
).
LocalMethod<infer function (type parameter) TT>
? type LocalEffect<
A,
E = never,
Self = unknown
> = Effect.Effect<A, E, Local<Self>>
A local-only member as surfaced in
ServiceOf
— Effect requiring
Local
to
obtain the value.
LocalEffect<function (type parameter) TT, never, function (type parameter) Self in type ServiceOf<S extends Spec, Self = unknown>Self>
: function (type parameter) S in type ServiceOf<S extends Spec, Self = unknown>S[function (type parameter) KK] extends { readonly _tag: "constant"_tag: "constant" }
? type SuccessOf<M extends AnyMethod> =
M["success"]["Type"]
SuccessOf<type AsMethod<T> = T extends {
readonly kind: MethodKind
readonly payload: infer P extends
| Schema.Struct.Fields
| Schema.Top
| undefined
readonly success: infer Su extends Schema.Top
readonly error: infer E extends Schema.Top
readonly stream: infer Str extends boolean
readonly annotations: infer Ann extends MethodAnnotations
}
? Method<P, Su, E, Str, Ann, Derive>
: never
Reconstruct a proper
Method
from a leaf's parts via infer — prop-presence + infer …
extends … is F-independent (reduces under a generic item schema) and keeps the payload precise,
unlike Extract/&. Lets the recursive spec types feed the existing ServiceMethod/ServeMethod/
RpcOf under a nested, generic Spec.
AsMethod<function (type parameter) S in type ServiceOf<S extends Spec, Self = unknown>S[function (type parameter) KK]>>
: function (type parameter) S in type ServiceOf<S extends Spec, Self = unknown>S[function (type parameter) KK] extends { readonly _tag: "ref"_tag: "ref" }
? interface Subscribable<A>A read-only reactive value: its current value (
Subscribable.get
, an Effect) plus a stream
of every change (
Subscribable.changes
). This is what a
ref
field surfaces — uniform local
and remote — and it's exactly the read side of a SubscriptionRef (Effect ships no Subscribable type in
this beta, so we name it here).
Subscribable<type SuccessOf<M extends AnyMethod> =
M["success"]["Type"]
SuccessOf<type AsMethod<T> = T extends {
readonly kind: MethodKind
readonly payload: infer P extends
| Schema.Struct.Fields
| Schema.Top
| undefined
readonly success: infer Su extends Schema.Top
readonly error: infer E extends Schema.Top
readonly stream: infer Str extends boolean
readonly annotations: infer Ann extends MethodAnnotations
}
? Method<P, Su, E, Str, Ann, Derive>
: never
Reconstruct a proper
Method
from a leaf's parts via infer — prop-presence + infer …
extends … is F-independent (reduces under a generic item schema) and keeps the payload precise,
unlike Extract/&. Lets the recursive spec types feed the existing ServiceMethod/ServeMethod/
RpcOf under a nested, generic Spec.
AsMethod<function (type parameter) S in type ServiceOf<S extends Spec, Self = unknown>S[function (type parameter) KK]>>>
: function (type parameter) S in type ServiceOf<S extends Spec, Self = unknown>S[function (type parameter) KK] extends { readonly kind: MethodKindkind: type MethodKind = "query" | "mutate"How a method behaves, for tools (CLI/TUI/dashboard) — explicit, never inferred;
encoded by the constructor used (
effect
vs
effectFn
):
query — an idempotent read (CLI prints it, dashboard reads it as an Atom);
mutate — a mutation (CLI confirms, dashboard calls it as runtime.fn).
MethodKind } // leaf (F-independent; reconstruct via AsMethod)
? type ClientMethod<
M extends AnyMethod,
Client
> = [Client] extends [Derive]
? ServiceMethod<M>
: Client
ClientMethod<type AsMethod<T> = T extends {
readonly kind: MethodKind
readonly payload: infer P extends
| Schema.Struct.Fields
| Schema.Top
| undefined
readonly success: infer Su extends Schema.Top
readonly error: infer E extends Schema.Top
readonly stream: infer Str extends boolean
readonly annotations: infer Ann extends MethodAnnotations
}
? Method<P, Su, E, Str, Ann, Derive>
: never
Reconstruct a proper
Method
from a leaf's parts via infer — prop-presence + infer …
extends … is F-independent (reduces under a generic item schema) and keeps the payload precise,
unlike Extract/&. Lets the recursive spec types feed the existing ServiceMethod/ServeMethod/
RpcOf under a nested, generic Spec.
AsMethod<function (type parameter) S in type ServiceOf<S extends Spec, Self = unknown>S[function (type parameter) KK]>, type ClientOverrideOf<T> =
T extends Method<
Schema.Struct.Fields | Schema.Top | undefined,
Schema.Top,
Schema.Top,
boolean,
MethodAnnotations,
infer Client
>
? Client
: Derive
ClientOverrideOf<function (type parameter) S in type ServiceOf<S extends Spec, Self = unknown>S[function (type parameter) KK]>> // client handle → override or derived
: function (type parameter) S in type ServiceOf<S extends Spec, Self = unknown>S[function (type parameter) KK] extends Spec
? type ServiceOf<S extends Spec, Self = unknown> = { [K in keyof { readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends {
readonly _tag: "constant";
} ? SuccessOf<AsMethod<S[K]>> : S[K] extends {
readonly _tag: "ref";
} ? Subscribable<SuccessOf<AsMethod<S[K]>>> : S[K] extends {
readonly kind: MethodKind;
} ? ClientMethod<...> : S[K] extends Spec ? Simplify<...> : never; }]: { readonly [K in keyof S]: S[K] extends FromLocalMethod<infer M> ? InjectLocal<M, Self> : S[K] extends LocalMethod<infer T> ? LocalEffect<T, never, Self> : S[K] extends {
readonly _tag: "constant";
} ? SuccessOf<AsMethod<S[K]>> : S[K] extends {
readonly _tag: "ref";
} ? Subscribable<SuccessOf<AsMethod<S[K]>>> : S[K] extends {
readonly kind: MethodKind;
} ? ClientMethod<...> : S[K] extends Spec ? Simplify<...> : never; }[K]; } extends infer B ? B : never
The full service interface inferred from a
Spec
. Wire
Method
s map to
Effect/function members; off-wire
LocalMethod
s surface as
Effect<T, never, Local<Self>> — yield* to obtain the value, requiring the local layer
(
Local
) (so they're uncallable through
Hyperlink.client
).
ServiceOf<function (type parameter) S in type ServiceOf<S extends Spec, Self = unknown>S[function (type parameter) KK], function (type parameter) Self in type ServiceOf<S extends Spec, Self = unknown>Self> // nested group → nested service
: never;
}>;