param name param value export function dateReviver ( name , value ) { if ( typeof value === "string" && /^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d.\d\d\dZ$/ . test ( value ) ) { return new Date ( value ) ; } return value ; } export function parseJsonOrDefault ( jsonString ) { try { return JSON . parse ( jsonString ) ; } catch ( error ) { console . error ( error ) ; return null ; } } export function hasAnyOwnProperty < T > ( obj , keys ) { return keys . some ( k => obj . hasOwnProperty ( k ) ) ; } export function isNullishOrEmpty ( obj ) { return obj == undefined || isEmptyArray ( obj ) ; } export function isEmptyArray ( obj ) { return Array . isArray ( obj ) && obj . length === 0 ; } type AccessorFunction < T , V > = ( obj : T ) => V ; type CompareFunction < T > = ( a : T , b : T ) => number ; export function numAsc < T , V extends number | bigint > ( accessor ) { return ( a , b ) => Number ( accessor ( a ) - accessor ( b ) ) ; } export function numDesc < T , V extends number | bigint > ( accessor ) { return ( a , b ) => Number ( accessor ( b ) - accessor ( a ) ) ; } /**
 * As of Jan 2020, bigint literals e.g. 1n can only be used with TS target esnext
 * which then doesn't transpile the null conditional/coalescing operators and breaks on Node 12
 * So BigInt(1) needs to be used here
 * */ export function incBigInt ( bigStr ) { return bigStr == undefined ? bigStr : String ( BigInt ( bigStr ) + BigInt ( 1 ) ) ; } export function decBigInt ( bigStr ) { return bigStr == undefined ? bigStr : String ( BigInt ( bigStr ) - BigInt ( 1 ) ) ; } export function parseBooleanExact ( val ) { if ( val === 'true' ) return true ; if ( val === 'false' ) return false ; return null ; } export function pickFields ( obj , fieldWhitelist ) { const subObject = { } ; for ( let [ key , value ] of Object . entries ( obj ) ) { if ( fieldWhitelist . has ( key ) ) { subObject [ key ] = value ; } } return subObject ; } /**
 * Generic type for a function validating that the argument is a object with
 * Used to enforce value types in a config object, but not obscuring the key names
 * by using a TS lookup type
 */ type ValueTypeCheck < C > = < K extends string > ( x : Record < K , C > ) => Record < K , C > ; /**
 * Creates a function that enforces all fields of its argument to be of type C
 * Useful to create configs where each field must be of a set type,
 * but the list of keys should be accessible to users of the config variable.
 */ export function valueType < C > ( ) { return x => x ; } /**
 * Map all properties of object through a function
 */ export function mapObject < T , R > ( x , fn ) { return Object . assign ( { } , ... Object . entries ( x ) . map ( ( [ key , value ] ) => ( { [ key ] : fn ( [ key as keyof T , value ] ) } ) ) ) ; }