| 
1 | 1 | import { action, autorun, computed, makeObservable, observable, when } from 'mobx'  | 
2 |  | -import { ValidationError, IState, Validation, ValidateResult, ValidateStatus, Validator } from './types'  | 
 | 2 | +import { ValidationError, IState, Validation, ValidateResult, ValidateStatus, Validator, WithSafeValue } from './types'  | 
3 | 3 | import Disposable from './disposable'  | 
4 | 4 | import { applyValidators, isValid, isPromiseLike } from './utils'  | 
5 | 5 | 
 
  | 
@@ -37,13 +37,18 @@ export abstract class BaseState extends Disposable implements Pick<  | 
37 | 37 | }  | 
38 | 38 | 
 
  | 
39 | 39 | /** Extraction for State's validating logic */  | 
40 |  | -export abstract class ValidatableState<V> extends BaseState implements IState<V> {  | 
 | 40 | +export abstract class ValidatableState<V, SV extends V> extends BaseState implements IState<V, SV> {  | 
41 | 41 | 
 
  | 
42 | 42 |   abstract value: V  | 
43 | 43 |   abstract touched: boolean  | 
44 | 44 |   abstract onChange(value: V): void  | 
45 | 45 |   abstract set(value: V): void  | 
46 | 46 | 
 
  | 
 | 47 | +  @computed get safeValue(): SV {  | 
 | 48 | +    if (!this.validated || this.hasError) throw new Error('TODO')  | 
 | 49 | +    return this.value as SV  | 
 | 50 | +  }  | 
 | 51 | + | 
47 | 52 |   /** The original validate status (regardless of `validationDisabled`) */  | 
48 | 53 |   @observable protected _validateStatus: ValidateStatus = ValidateStatus.NotValidated  | 
49 | 54 | 
 
  | 
@@ -76,9 +81,9 @@ export abstract class ValidatableState<V> extends BaseState implements IState<V>  | 
76 | 81 |   /** List of validator functions. */  | 
77 | 82 |   @observable.shallow private validatorList: Validator<V>[] = []  | 
78 | 83 | 
 
  | 
79 |  | -  @action withValidator(...validators: Validator<V>[]) {  | 
 | 84 | +  @action withValidator<NSV = SV>(...validators: Validator<V>[]): WithSafeValue<this, NSV> {  | 
80 | 85 |     this.validatorList.push(...validators)  | 
81 |  | -    return this  | 
 | 86 | +    return this as WithSafeValue<this, NSV>  | 
82 | 87 |   }  | 
83 | 88 | 
 
  | 
84 | 89 |   /** Current validation info. */  | 
@@ -108,15 +113,15 @@ export abstract class ValidatableState<V> extends BaseState implements IState<V>  | 
108 | 113 |     })()  | 
109 | 114 |   }  | 
110 | 115 | 
 
  | 
111 |  | -  @computed protected get validateResult(): ValidateResult<V> {  | 
 | 116 | +  @computed protected get validateResult(): ValidateResult<SV> {  | 
112 | 117 |     return (  | 
113 | 118 |       this.error  | 
114 |  | -      ? { hasError: true, error: this.error } as const  | 
115 |  | -      : { hasError: false, value: this.value } as const  | 
 | 119 | +      ? { hasError: true, error: this.error }  | 
 | 120 | +      : { hasError: false, value: this.value as SV }  | 
116 | 121 |     )  | 
117 | 122 |   }  | 
118 | 123 | 
 
  | 
119 |  | -  async validate(): Promise<ValidateResult<V>> {  | 
 | 124 | +  async validate(): Promise<ValidateResult<SV>> {  | 
120 | 125 |     if (this.disabled) {  | 
121 | 126 |       return this.validateResult  | 
122 | 127 |     }  | 
 | 
0 commit comments