Validate<C, I>Validate a fromService contract C against its service interface I: a bare
local at a key absent from I (or with no I at all) becomes a LocalNeedsType
error the user's value can't satisfy, so the contract argument is rejected at the call site.
Every other entry (a wired method, an explicit local<T>(), a nested group) passes through.
export type type Validate<C, I> = {
readonly [K in keyof C]: C[K] extends BareLocal
? K extends keyof I
? C[K]
: LocalNeedsType<K>
: C[K] extends Spec
? K extends keyof I
? Validate<C[K], I[K]>
: LocalNeedsType<K>
: C[K] extends {
readonly kind: MethodKind
}
? K extends keyof I
? WireHonors<
SuccessOf<AsMethod<C[K]>>,
IfaceSuccess<I[K]>
> extends true
? C[K]
: WireMismatch<K>
: C[K]
: C[K]
}
Validate a
fromService
contract C against its service interface I: a bare
local
at a key absent from I (or with no I at all) becomes a
LocalNeedsType
error the user's value can't satisfy, so the contract argument is rejected at the call site.
Every other entry (a wired method, an explicit local<T>(), a nested group) passes through.
Validate<function (type parameter) C in type Validate<C, I>C, function (type parameter) I in type Validate<C, I>I> = {
readonly [function (type parameter) KK in keyof function (type parameter) C in type Validate<C, I>C]: function (type parameter) C in type Validate<C, I>C[function (type parameter) KK] extends BareLocal
? function (type parameter) KK extends keyof function (type parameter) I in type Validate<C, I>I
? function (type parameter) C in type Validate<C, I>C[function (type parameter) KK]
: interface LocalNeedsType<K extends PropertyKey>The error surface a bare
local
resolves to when the service interface has no member at that
key — a required, unsatisfiable field, so the whole contract argument fails to type-check at the
call.
LocalNeedsType<function (type parameter) KK>
: function (type parameter) C in type Validate<C, I>C[function (type parameter) KK] extends Spec
? function (type parameter) KK extends keyof function (type parameter) I in type Validate<C, I>I
? type Validate<C, I> = {
readonly [K in keyof C]: C[K] extends BareLocal
? K extends keyof I
? C[K]
: LocalNeedsType<K>
: C[K] extends Spec
? K extends keyof I
? Validate<C[K], I[K]>
: LocalNeedsType<K>
: C[K] extends {
readonly kind: MethodKind
}
? K extends keyof I
? WireHonors<
SuccessOf<AsMethod<C[K]>>,
IfaceSuccess<I[K]>
> extends true
? C[K]
: WireMismatch<K>
: C[K]
: C[K]
}
Validate a
fromService
contract C against its service interface I: a bare
local
at a key absent from I (or with no I at all) becomes a
LocalNeedsType
error the user's value can't satisfy, so the contract argument is rejected at the call site.
Every other entry (a wired method, an explicit local<T>(), a nested group) passes through.
Validate<function (type parameter) C in type Validate<C, I>C[function (type parameter) KK], function (type parameter) I in type Validate<C, I>I[function (type parameter) KK]>
: interface LocalNeedsType<K extends PropertyKey>The error surface a bare
local
resolves to when the service interface has no member at that
key — a required, unsatisfiable field, so the whole contract argument fails to type-check at the
call.
LocalNeedsType<function (type parameter) KK>
: function (type parameter) C in type Validate<C, I>C[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 } // a wired method
? function (type parameter) KK extends keyof function (type parameter) I in type Validate<C, I>I
? type WireHonors<W, I> = [W] extends [I]
? true
: false
Does a wired member's success W honor the interface's success promise I (is it assignable to
it)? Tuple-wrapped so neither side distributes. A schema subtype (e.g. Array for a ReadonlyArray
interface member) still honors it; a genuine mismatch (string for number) does not.
WireHonors<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) C in type Validate<C, I>C[function (type parameter) KK]>>, type IfaceSuccess<T> = T extends (
...args: any
) => infer R
? R extends Effect.Effect<infer A, any, any>
? A
: R extends Stream.Stream<infer A, any, any>
? A
: R
: T extends Effect.Effect<infer A, any, any>
? A
: T extends Stream.Stream<infer A, any, any>
? A
: T
The success (element) type of a service interface member — the A of its returned Effect/Stream
(through a function), else the member itself. Used to check a wired contract member's schema against
the interface.
IfaceSuccess<function (type parameter) I in type Validate<C, I>I[function (type parameter) KK]>> extends true
? function (type parameter) C in type Validate<C, I>C[function (type parameter) KK]
: interface WireMismatch<K extends PropertyKey>The error surface a wired
fromService
member resolves to when its success schema disagrees
with the service interface at that key — rejected at the call, naming the key.
WireMismatch<function (type parameter) KK>
: function (type parameter) C in type Validate<C, I>C[function (type parameter) KK] // wired member absent from the interface — allowed (interface may be a subset view)
: function (type parameter) C in type Validate<C, I>C[function (type parameter) KK];
};