import isPlainObject from 'lodash-es/isPlainObject' ; import type { $IntentionalAny } from './types' ; enum ValueType { Opaque = 0 , Array = 1 , Object = 2 } function typeOfValue ( v ) { if ( typeof v === 'object' && v !== null ) { if ( Array . isArray ( v ) ) { return ValueType . Array ; } else if ( isPlainObject ( v ) ) { return ValueType . Object ; } else { return ValueType . Opaque ; } } else { return ValueType . Opaque ; } } remarks export default function minimalOverride < T > ( base , override ) { const typeofOverride = typeOfValue ( override ) ; if ( typeofOverride === ValueType . Opaque ) { return override ; } const typeofBase = typeOfValue ( base ) ; if ( base === override ) return override ; if ( typeofOverride !== typeofBase ) return override ; if ( typeofOverride === ValueType . Object ) { return minimalOverrideObject ( base , override ) ; } else { return minimalOverrideArray ( base as $IntentionalAny , override ) as $IntentionalAny ; } } function minimalOverrideObject < T extends { } > ( base , override ) { const o = { } ; let atLeastOneKeyWasDifferent = false ; const keysOfOverride = Object . keys ( override ) as Array < keyof T > ; for ( const key of keysOfOverride ) { const baseVal = base [ key ] ; const overrideVal = override [ key ] ; const minimalOverrideVal = minimalOverride ( baseVal , overrideVal ) ; o [ key ] = minimalOverrideVal ; if ( minimalOverrideVal !== baseVal ) { atLeastOneKeyWasDifferent = true ; } } if ( atLeastOneKeyWasDifferent ) { return o ; } else { if ( Object . keys ( base ) . length === keysOfOverride . length ) { return base ; } else { return o ; } } } function minimalOverrideArray < T extends $IntentionalAny [ ] > ( base , override ) { if ( base . length !== override . length ) return override ; return base . every ( ( val , i ) => val === override [ i ] ) ? base : override ; }