export class AssertError extends Error { constructor ( valueName , value , message ) { super ( `Invalid ${ valueName }: ${ message }. Got: ${ value }` ) ; } } type AssertionValue = string | number | object | AssertionValue [ ] ; type AssertFunction = ( v : AssertionValue ) => false | { error : string ; value : AssertionValue ; } ; export const assert = ( valueName , value , assertFunction ) => { const assertion = assertFunction ( value ) ; if ( assertion ) { throw new AssertError ( valueName , assertion . value , assertion . error ) ; } } ; export const isInstanceOf = ( klass ) : AssertFunction => v => ( v instanceof klass ? false : { error : `expected instance of ${ klass . name }` , value : v } ) ; export const isNumber = v => ( Number . isFinite ( v ) ? false : { error : 'expected number' , value : v } ) ; export const isString = v => ( typeof v === 'string' ? false : { error : 'expected string' , value : v } ) ; export const isFunction = v => ( typeof v === 'function' ? false : { error : 'expected function' , value : v } ) ; export const isPlainObject = v => ( isPlainObjectImpl ( v ) ? false : { error : 'expected literal object' , value : v } ) ; export const isArray = ( assertFunction ) : AssertFunction => v => { if ( ! Array . isArray ( v ) ) { return { error : 'expected array' , value : v , } ; } const assertions = v . map ( assertFunction ) ; return assertions . find ( Boolean ) ?? false ; } ; const isPlainObjectImpl = ( obj ) => { return typeof obj === 'object' && obj !== null && obj . constructor === Object && Object . prototype . toString . call ( obj ) === '[object Object]' ; } ;