@@ -100,11 +100,6 @@ type ErrorMap = Record<
100100 }
101101> ;
102102
103- type FeatureFn < ErrorType extends string > = (
104- featureName : string ,
105- featureContextExtendedParams ?: ExtendedParams
106- ) => CreateErrorFn < ErrorType > ;
107-
108103type ErrorFnOptions = {
109104 originalError ?: OriginalError ;
110105 extendedParams ?: ExtendedParams ;
@@ -116,23 +111,37 @@ type CreateErrorFn<ErrorType extends string> = (
116111 options ?: ErrorFnOptions
117112) => IConwayError ;
118113
119- type ErrorSubcontext < ErrorType extends string > = {
114+ type Brand < T , B > = T & { __brand : B } ;
115+
116+ type ErrorSubcontext < Name extends string , ErrorType extends string > = Brand < Subcontext < Name , ErrorType > , Name > ;
117+ type ErrorFeature < Name extends string , ErrorType extends string > = Brand < CreateErrorFn < ErrorType > , Name > ;
118+ export type AnyFeatureOfSubcontext < S > = S extends ErrorSubcontext < infer Name , infer ErrorType >
119+ ? ErrorFeature < `${Name } /${string } `, ErrorType >
120+ : never ;
121+
122+ type Subcontext < Name extends string , ErrorType extends string > = {
120123 /**
121124 * Create a child context within the current context.
122125 *
123126 * @param {string } childContextName - The name of the child context.
124127 * @param {ExtendedParams } extendedParams - Additional extended parameters for the child context.
125128 * @return {Function } Function to create an error context with the specified child context name and extended params.
126129 */
127- subcontext : ( subcontextName : string , extendedParams ?: ExtendedParams ) => ErrorSubcontext < ErrorType > ;
130+ subcontext : < const ChildContextName extends string > (
131+ subcontextName : ChildContextName ,
132+ extendedParams ?: ExtendedParams
133+ ) => ErrorSubcontext < `${Name } /${ChildContextName } `, ErrorType > ;
128134 /**
129135 * Creates a child feature within the current context.
130136 *
131137 * @param {string } childFeatureName - The name of the child feature.
132138 * @param {ExtendedParams } [extendedParams={}] - Additional extended parameters for the child feature.
133139 * @return {Function } The created error feature.
134140 */
135- feature : FeatureFn < ErrorType > ;
141+ feature : < const FeatureName extends string > (
142+ featureName : FeatureName ,
143+ featureContextExtendedParams ?: ExtendedParams
144+ ) => ErrorFeature < `${Name } /${FeatureName } `, ErrorType > ;
136145} ;
137146
138147/**
@@ -146,7 +155,7 @@ export function createError<ErrorTypes extends ErrorTypeConfig>(errorTypes?: Err
146155 const _options = { ...defaultErrorOptions , ...options } ;
147156 const initialExtendedParams = options ?. extendedParams ?? { } ;
148157
149- return ( contextName : string , extendedParams : ExtendedParams = { } ) => {
158+ return < const ContextName extends string > ( contextName : ContextName , extendedParams : ExtendedParams = { } ) => {
150159 const outerExtendedParams = { ...initialExtendedParams , ...extendedParams } ;
151160
152161 const errorsMap : ErrorMap = Array . isArray ( errorTypes )
@@ -162,30 +171,37 @@ export function createError<ErrorTypes extends ErrorTypeConfig>(errorTypes?: Err
162171 const UnknownError = createErrorClass ( "UnknownError" , contextName ) ;
163172
164173 const _createSubcontext =
165- ( contextName : string , subContextExtendedParams : ExtendedParams ) =>
166- ( childContextName : string , extendedParams : ExtendedParams = { } ) => {
174+ < const ContextName extends string > ( contextName : ContextName , subContextExtendedParams : ExtendedParams ) =>
175+ < const ChildContextName extends string > (
176+ childContextName : ChildContextName ,
177+ extendedParams : ExtendedParams = { }
178+ ) => {
167179 const subErrorContext = { ...subContextExtendedParams , ...extendedParams } ;
168180 return _createErrorContext ( `${ contextName } /${ childContextName } ` , subErrorContext ) ;
169181 } ;
170182
171- function _createErrorContext (
172- _contextName : string ,
183+ function _createErrorContext < const ContextName extends string > (
184+ _contextName : ContextName ,
173185 contextExtendedParams : ExtendedParams = outerExtendedParams
174- ) : ErrorSubcontext < ErrorTypes [ number ] [ "errorType" ] > {
186+ ) : ErrorSubcontext < ContextName , ErrorTypes [ number ] [ "errorType" ] > {
175187 return {
188+ __brand : _contextName ,
176189 subcontext : _createSubcontext ( _contextName , contextExtendedParams ) ,
177- feature : ( childFeatureName : string , extendedParams : ExtendedParams = { } ) => {
190+ feature : < const FeatureName extends string > (
191+ childFeatureName : FeatureName ,
192+ extendedParams : ExtendedParams = { }
193+ ) => {
178194 const featureErrorContext = { ...contextExtendedParams , ...extendedParams } ;
179195 return _createErrorFeature ( childFeatureName , _contextName , featureErrorContext ) ;
180196 } ,
181197 } ;
182198 }
183199
184- function _createErrorFeature (
185- featureName : string ,
186- contextName : string ,
200+ function _createErrorFeature < const ContextName extends string , const FeatureName extends string > (
201+ featureName : FeatureName ,
202+ contextName : ContextName ,
187203 featureContextExtendedParams : ExtendedParams = { }
188- ) {
204+ ) : ErrorFeature < `${ ContextName } /${ FeatureName } ` , ErrorTypes [ number ] [ "errorType" ] > {
189205 const createNewErrorObject : CreateErrorFn < ErrorTypes [ number ] [ "errorType" ] > = (
190206 errorType ,
191207 message : string ,
@@ -215,7 +231,8 @@ export function createError<ErrorTypes extends ErrorTypeConfig>(errorTypes?: Err
215231 return error ;
216232 } ;
217233
218- return createNewErrorObject ;
234+ Object . assign ( createNewErrorObject , { __brand : `${ contextName } /${ featureName } ` as const } ) ;
235+ return createNewErrorObject as ErrorFeature < `${ContextName } /${FeatureName } `, ErrorTypes [ number ] [ "errorType" ] > ;
219236 }
220237
221238 return _createErrorContext ( contextName ) ;
0 commit comments