Type System
Nile's type system provides compile-time safety for action payloads, handler parameters, and client responses, while using Zod for runtime validation.
Generic Action Types
Action<T, E> and ActionHandler<T, E> are generic types. T represents the payload or result type. E represents the error type. createAction<T, E> preserves type inference through the action lifecycle.
Type Flow
Types flow through the system in a defined sequence:
ActionHandler<T, E>— handler receivesdata: T, returnsResult<unknown, E>Action<T, E>— the action config carries generics through registrationcreateAction<T, E>()— returnsAction<T, E>, preserving inference- Zod validation guarantees
datamatchesTbefore handler execution
The handler parameter data is typed at compile time. Zod validates at runtime. Both must align.
Collection Boundaries
Actions collected into a Service lose individual T types. TypeScript lacks existential types. Actions = Action<any, any>[] is a heterogeneous collection boundary.
Individual actions retain full type safety via createAction<T>(). Type erasure occurs only at the service registration boundary. This is a deliberate trade-off for runtime flexibility.
Client-Side Type Safety
ExternalResponse<T>, ClientResult<T>, and createNileClient<TPayloads>() provide typed client interactions. The TPayloads generic encodes service and action shapes.
Invalid service names, action names, or payload shapes produce compile-time errors.
Discovery and Schema Generation
The explore and schema intents provide runtime type information. schema exports Zod schemas as JSON Schema for code generation.
Generated types from schemas can seed TPayloads interfaces. See Actions for intent details.
Type Safety Boundaries
Type safety is enforced at action definition and client invocation. Runtime validation via Zod bridges the gap at collection and engine boundaries.