@@ -69,9 +69,18 @@ export type ValidationResult<TSteps extends readonly ValidationStepConfig<any, a
6969 errors : Partial < ExtractStepResults < TSteps > > ;
7070} ;
7171
72- // Extract TInput from the first step's validator function
72+ // Util: convert a union to an intersection
73+ type UnionToIntersection < U > = ( U extends any ? ( arg : U ) => void : never ) extends ( arg : infer I ) => void
74+ ? I
75+ : never ;
76+
77+ // Extract the *intersection* of all input types required by the steps. This guarantees that
78+ // the resulting processor knows about every property that any individual step relies on.
79+ // We purposely compute an intersection (not a union) so that all required fields are present.
7380type ExtractInputType < TSteps extends readonly ValidationStepConfig < any , any , string > [ ] > =
74- TSteps [ number ] extends ValidationStepConfig < infer TInput , any , string > ? TInput : never ;
81+ UnionToIntersection <
82+ TSteps [ number ] extends ValidationStepConfig < infer TInput , any , string > ? TInput : never
83+ > ;
7584
7685/**
7786 * Creates a type-safe validation processor that executes a series of validation steps
@@ -162,17 +171,23 @@ type ExtractInputType<TSteps extends readonly ValidationStepConfig<any, any, str
162171export function createValidationProcessor <
163172 const TSteps extends readonly ValidationStepConfig < any , any , string > [ ] ,
164173> ( definition : { steps : TSteps } ) {
165- type TInput = ExtractInputType < TSteps > ;
174+ // Determine the base input type required by all steps (intersection).
175+ type BaseInput = ExtractInputType < TSteps > ;
176+
177+ // Helper: widen input type for object literals while keeping regular objects assignable.
178+ type InputWithExtras = BaseInput extends object
179+ ? BaseInput | ( BaseInput & Record < string , unknown > )
180+ : BaseInput ;
166181
167182 return function processValidation (
168- input : TInput ,
183+ input : InputWithExtras ,
169184 config : ValidationPipelineConfig = { }
170185 ) : ValidationResult < TSteps > {
171186 const errors : Partial < ExtractStepResults < TSteps > > = { } ;
172187 let hasErrors = false ;
173188
174189 for ( const step of definition . steps ) {
175- const result = step . validator ( input ) ;
190+ const result = step . validator ( input as BaseInput ) ;
176191 const isError = step . isError ( result ) ;
177192
178193 if ( isError ) {
0 commit comments