import { ComparableData } from '../interfaces/comparable-data-type';
/**
 * @description
 * Updates or inserts (if does not exist) one or multiple items in an array T[].
 * For comparison you can provide a key, an array of keys or a custom comparison function that should return true if
 * items match.
 * If no comparison is provided, an equality check is used by default.
 * upsert is `pure` and `immutable`, your inputs won't be changed
 *
 *
 * @example
 * // Upsert (update) with key
 *
 * const creatures = [{id: 1, type: 'cat'}, {id: 2, type: 'dog'}];
 *
 * const newCat = {id: 1, type: 'lion'};
 *
 * const updatedCreatures = upsert(creatures, newCat, 'id');
 *
 * // updatedCreatures will be:
 * // [{id: 1, type: 'lion'}, {id: 2, type: 'dog'}];
 *
 * @example
 * // Upsert (insert) with key
 *
 * const creatures = [{id: 1, type: 'cat'}, {id: 2, type: 'dog'}];
 *
 * const newCat = {id: 3, type: 'lion'};
 *
 * const updatedCreatures = upsert(creatures, newCat, 'id');
 *
 * // updatedCreatures will be:
 * // [{id: 1, type: 'cat'}, {id: 2, type: 'dog'}, {id: 3, type: 'lion'}];
 *
 * @example
 * // Upsert (update) with array of keys
 *
 * const creatures = [{id: 1, type: 'cat', name: 'Bella'}, {id: 2, type: 'dog', name: 'Sparky'}];
 *
 * const newCat = {id: 1, type: 'lion', name: 'Bella'};
 *
 * const updatedCreatures = upsert(creatures, newCat, ['id', 'name']);
 *
 * // updatedCreatures will be:
 * // [{id: 1, type: 'lion', name: 'Bella'}, {id: 2, type: 'dog', name: 'Sparky'}];
 *
 * @example
 * // Update (insert) with comparison function
 *
 * const creatures = [{id: 1, type: 'cat'}, {id: 2, type: 'dog'}];
 *
 * const newCat = {id: 3, type: 'lion'};
 *
 * const updatedCreatures = upsert(creatures, newCat, (a, b) => a.id === b.id);
 *
 * // updatedCreatures will be:
 * // [{id: 1, type: 'cat'}, {id: 2, type: 'dog'}, {id: 3, type: 'lion'}];
 *
 * @example
 * // Usage with RxState
 *
 * export class ListComponent {
 *
 *    // trigger which gets called on add/update (for reactive implementation)
 *    readonly addOrUpdateCreature = new Subject<Creature>();
 *
 *    constructor(private state: RxState<ComponentState>) {
 *      const initialCreatures = [{id: 1, type: 'cat', name: 'Bella'}, {id: 2, type: 'dog', name: 'Sparky'}];
 *      state.set({ creatures: initialCreatures });
 *      // Reactive implementation
 *      state.connect(
 *        'creatures',
 *        this.addOrUpdateCreature,
 *        ({ creatures }, creatureToUpsert) => {
 *            return upsert(creatures, creatureToUpsert, 'id');
 *        }
 *      );
 *    }
 *
 *    // Imperative implementation
 *    updateCreature(creatureToUpdate: Creature): void {
 *        this.state.set({ creatures: upsert(this.state.get('creatures'), creatureToUpdate, 'id')});
 *    }
 * }
 *
 * @returns T[]
 *
 * @docsPage upsert
 * @docsCategory transformation-helpers
 */
export declare function upsert<T>(source: T[], update: Partial<T>[] | Partial<T>, compare?: ComparableData<T>): T[];
