import { isStateTreeNode , getStateTreeNode , IValidationContext , IValidationResult , typeCheckSuccess , typeCheckFailure , isType , fail , TypeFlags , IAnyType , AnyObjectNode , BaseType , ExtractNodeType , assertIsType , devMode } from "../../internal" ; import { assertIsString , assertIsFunction } from "../../utils" ; class Refinement < IT extends IAnyType > extends BaseType < IT [ "CreationType" ] , IT [ "SnapshotType" ] , IT [ "TypeWithoutSTN" ] , ExtractNodeType < IT > > { get flags ( ) { return this . _subtype . flags | TypeFlags . Refinement ; } constructor ( name , private readonly _subtype , private readonly _predicate , private readonly _message ) { super ( name ) ; } describe ( ) { return this . name ; } instantiate ( parent , subpath , environment , initialValue ) { return this . _subtype . instantiate ( parent , subpath , environment , initialValue ) as any ; } isAssignableFrom ( type ) { return this . _subtype . isAssignableFrom ( type ) ; } isValidSnapshot ( value , context ) { const subtypeErrors = this . _subtype . validate ( value , context ) ; if ( subtypeErrors . length > 0 ) return subtypeErrors ; const snapshot = isStateTreeNode ( value ) ? getStateTreeNode ( value ) . snapshot : value ; if ( ! this . _predicate ( snapshot ) ) { return typeCheckFailure ( context , value , this . _message ( value ) ) ; } return typeCheckSuccess ( ) ; } reconcile ( current , newValue , parent , subpath ) { return this . _subtype . reconcile ( current , newValue , parent , subpath ) as any ; } getSubTypes ( ) { return this . _subtype ; } } export function refinement < IT extends IAnyType > ( name , type , predicate , message ? ) ; export function refinement < IT extends IAnyType > ( type , predicate , message ? ) ; param name param type param predicate returns export function refinement ( ... args ) { const name = typeof args [ 0 ] === "string" ? args . shift ( ) : isType ( args [ 0 ] ) ? args [ 0 ] . name : null ; const type = args [ 0 ] ; const predicate = args [ 1 ] ; const message = args [ 2 ] ? args [ 2 ] : ( v ) => "Value does not respect the refinement predicate" ; assertIsType ( type , [ 1 , 2 ] ) ; assertIsString ( name , 1 ) ; assertIsFunction ( predicate , [ 2 , 3 ] ) ; assertIsFunction ( message , [ 3 , 4 ] ) ; return new Refinement ( name , type , predicate , message ) ; } param type returns export function isRefinementType < IT extends IAnyType > ( type ) { return ( type . flags & TypeFlags . Refinement ) > 0 ; }