/** * @description * Accepts an array of objects of type T and single key or array of keys (K extends keyof T). * The `extract` method is pure and immutable, thus not touching the input values and returning a shallow * copy of the extracted source. * * @example * * const cats = [{id: 1, type: 'cat', name: 'Fluffy'}, {id: 2, type: 'cat', name: 'Emma'}]; * * const catsWithoutTypes = extract(cats, ['name', 'id']); * * // catsWithoutTypes will be: * // [{id: 1, name: 'Fluffy'}, {id: 2, name: 'Emma'}]; * * @example * // Usage with RxState * * export class AnimalsListComponent { * * constructor(private state: RxState, private api: ApiService) { * state.connect( * 'animals', * this.api.getAnimals(), * (state, animals) => extract(animals, ['id', 'name']) * ); * } * } * * @returns Pick[] * * @docsPage extract * @docsCategory transformation-helpers */ declare function extract(array: T[], keys: K | K[]): Pick[]; /** * @description * Inserts one or multiple items to an array T[]. * Returns a shallow copy of the updated array T[], and does not mutate the original one. * * @example * // Inserting single value * * const creatures = [{id: 1, type: 'cat'}, {id: 2, type: 'dog'}]; * * const updatedCreatures = insert(creatures, {id: 3, type: 'parrot'}); * * // updatedCreatures will be: * // [{id: 1, type: 'cat'}, {id: 2, type: 'dog}, {id: 3, type: 'parrot}]; * * @example * // Inserting multiple values * * const creatures = [{id: 1, type: 'cat'}, {id: 2, type: 'dog'}]; * * const updatedCreatures = insert(creatures, [{id: 3, type: 'parrot'}, {id: 4, type: 'hamster'}]); * * // updatedCreatures will be: * // [{id: 1, type: 'cat'}, {id: 2, type: 'dog'}, {id: 3, type: 'parrot'}, {id: 4, type: 'hamster'}]; * * @example * // Usage with RxState * * export class ListComponent { * * readonly insertCreature$ = new Subject(); * * constructor(private state: RxState) { * // Reactive implementation * state.connect( * 'creatures', * this.insertCreature$, * ({ creatures }) => { * const creatureToAdd = {id: generateId(), name: 'newCreature', type: 'dinosaur' }; * return insert(creatures, creatureToAdd); * } * ); * } * * // Imperative implementation * insertCreature(): void { * const creatureToAdd = {id: generateId(), name: 'newCreature', type: 'dinosaur' }; * this.state.set({ creatures: insert(this.state.get().creatures, creatureToAdd)}); * } * } * * * @returns T[] * * @docsPage insert * @docsCategory transformation-helpers */ declare function insert(source: T[], updates: T | T[]): T[]; /** * @description * The function which is used by `KeyCompareMap` to determine if changes are distinct or not. * Should return true if values are equal. * * @param {T} oldVal * @param {T} newVal * * @return boolean * * @docsPage interfaces * @docsCategory operators */ type CompareFn = (oldVal: T, newVal: T) => boolean; type ComparableData = CompareFn | keyof T | (keyof T)[]; /** * @description * Removes one or multiple items from 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 data is provided, an equality check is used by default. * Returns a shallow copy of the updated array T[], and does not mutate the original one. * * @example * // Removing value without comparison data * * const items = [1,2,3,4,5]; * * const updatedItems = remove(items, [1,2,3]); * * // updatedItems will be: [4,5]; * * @example * // Removing values with comparison function * * const creatures = [{id: 1, type: 'cat'}, {id: 2, type: 'unicorn'}, {id: 3, type: 'kobold'}]; * * const nonExistingCreatures = [{id: 2, type: 'unicorn'}, {id: 3, type: 'kobold'}]; * * const realCreatures = remove(creatures, nonExistingCreatures, (a, b) => a.id === b.id); * * // realCreatures will be: [{id: 1, type: 'cat'}]; * * @example * // Removing values with key * * const creatures = [{id: 1, type: 'cat'}, {id: 2, type: 'unicorn'}, {id: 3, type: 'kobold'}]; * * const nonExistingCreatures = [{id: 2, type: 'unicorn'}, {id: 3, type: 'kobold'}]; * * const realCreatures = remove(creatures, nonExistingCreatures, 'id'); * * // realCreatures will be: [{id: 1, type: 'cat'}]; * * @example * // Removing values with array of keys * * const creatures = [{id: 1, type: 'cat'}, {id: 2, type: 'unicorn'}, {id: 3, type: 'kobold'}]; * * const nonExistingCreatures = [{id: 2, type: 'unicorn'}, {id: 3, type: 'kobold'}]; * * const realCreatures = remove(creatures, nonExistingCreatures, ['id', 'type']); * * // realCreatures will be: [{id: 1, type: 'cat'}]; * * @example * // Usage with RxState * * export class ListComponent { * * readonly removeCreature$ = new Subject(); * * constructor(private state: RxState) { * // Reactive implementation * state.connect( * 'creatures', * this.removeCreature$, * ({ creatures }, creatureToRemove) => { * return remove(creatures, creatureToRemove, (a, b) => a.id === b.id); * } * ); * } * * // Imperative implementation * removeCreature(creatureToRemove: Creature): void { * this.state.set({ creatures: remove(this.state.get().creatures, creatureToRemove, (a, b) => a.id === b.id)}); * } * } * * @returns T[] * * @docsPage remove * @docsCategory transformation-helpers */ declare function remove(source: T[], scrap: Partial[] | Partial, compare?: ComparableData): T[]; /** * @description * Allows to pass only keys which value is of specific type. * * @example * * interface Creature { * id: number; * type: string; * name: string; * } * * const cat = {id: 1, type: 'cat', name: 'Fluffy'}; * * function updateCreature(creature: T, key: OnlyKeysOfSpecificType, value: string) { * // update logic * } * * // Valid key * updateCreature(cat, 'name', 'Luna'); * * // Invalid key * updateCreature(cat, 'id', 3); * * @docsPage OnlyKeysOfSpecificType * @docsCategory interfaces */ type OnlyKeysOfSpecificType = { [Key in keyof T]: S extends T[Key] ? Key : never; }[keyof T]; /** * @description * Converts an array of objects to a dictionary {[key: string]: T}. * Accepts array T[] and key of type string, number or symbol as inputs. * * * @example * * const creatures = [{id: 1, type: 'cat'}, {id: 2, type: 'dog'}, {id: 3, type: 'parrot'}]; * * const creaturesDictionary = toDictionary(creatures, 'id'); * * // creaturesDictionary will be: * // { * // 1: {id: 1, type: 'cat'}, * // 2: {id: 2, type: 'dog'}, * // 3: {id: 3, type: 'parrot'} * // }; * @example * // Usage with RxState * * export class ListComponent { * * readonly convertToDictionary$ = new Subject(); * * constructor(private state: RxState) { * // Reactive implementation * state.connect( * 'creaturesDictionary', * this.convertToDictionary$, * ({ creatures }) => { * return toDictionary(creatures, 'id'); * } * ); * } * * // Imperative implementation * convertToDictionary(): void { * this.state.set({ creaturesDictionary: toDictionary(this.state.get().creatures, 'id')}); * } * } * * @see {@link OnlyKeysOfSpecificType} * @param {OnlyKeysOfSpecificType} key * @returns { [key: string]: T } * @docsPage toDictionary * @docsCategory transformation-helpers */ declare function toDictionary(source: T[], key: OnlyKeysOfSpecificType | OnlyKeysOfSpecificType | OnlyKeysOfSpecificType): { [key: string]: T; }; /** * @description * Updates one or multiple items in an array T[]. * For comparison you can provide key, 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. * Returns a shallow copy of the array T[] and updated items, does not mutate the original array. * * @example * // Update with comparison function * * const creatures = [{id: 1, type: 'cat'}, {id: 2, type: 'dog'}]; * * const newCat = {id: 1, type: 'lion'}; * * const updatedCreatures = update(creatures, newCat, (a, b) => a.id === b.id); * * // updatedCreatures will be: * // [{id: 1, type: 'lion'}, {id: 2, type: 'dog'}]; * * @example * // Update with key * * const creatures = [{id: 1, type: 'cat'}, {id: 2, type: 'dog'}]; * * const newCat = {id: 1, type: 'lion'}; * * const updatedCreatures = update(creatures, newCat, 'id'); * * // updatedCreatures will be: * // [{id: 1, type: 'lion'}, {id: 2, type: 'dog'}]; * * @example * // 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 = update(creatures, newCat, ['id', 'name']); * * // updatedCreatures will be: * // [{id: 1, type: 'lion', name: 'Bella'}, {id: 2, type: 'dog', name: 'Sparky'}]; * * @example * // Usage with RxState * * export class ListComponent { * * readonly updateCreature$ = new Subject(); * * constructor(private state: RxState) { * // Reactive implementation * state.connect( * 'creatures', * this.updateCreature$, * ({ creatures }, creatureToUpdate) => { * return update(creatures, creatureToUpdate, (a, b) => a.id === b.id); * } * ); * } * * // Imperative implementation * updateCreature(creatureToUpdate: Creature): void { * this.state.set({ creatures: update(this.state.get().creatures, creatureToUpdate, (a, b) => a.id === b.id)}); * } * } * * @returns T[] * * @docsPage update * @docsCategory transformation-helpers */ declare function update(source: T[], updates: Partial[] | Partial, compare?: ComparableData): T[]; /** * @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(); * * constructor(private state: RxState) { * 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 */ declare function upsert(source: T[], update: Partial[] | Partial, compare?: ComparableData): T[]; /** * @description * Accepts an object of type T and key of type K extends keyof T. * Removes property from an object and returns a shallow copy of the updated object without specified property. * If property not found returns copy of the original object. * Not mutating original object. * * @example * * const cat = {id: 1, type: 'cat', name: 'Fluffy'}; * * const anonymusCat = deleteProp(cat, 'name'); * * // anonymusCat will be: * // {id: 1, type: 'cat'}; * * @example * // Usage with RxState * * export class ProfileComponent { * * readonly removeName$ = new Subject(); * * constructor(private state: RxState) { * // Reactive implementation * state.connect( * this.removeName$, * (state) => { * return deleteProp(state, 'name'); * } * ); * } * * // Imperative implementation * removeName(): void { * this.state.set(deleteProp(this.state.get(), 'name')); * } * } * * @returns Omit * * @docsPage deleteProp * @docsCategory transformation-helpers */ declare function deleteProp(object: T, key: K): Omit; /** * @description * Converts a dictionary of type {[key: string]: T} to array T[]. * * @example * * const creaturesDictionary = { * '1': {id: 1, type: 'cat'}, * '2': {id: 2, type: 'dog'}, * '3': {id: 3, type: 'parrot'} * }; * * const creaturesArray = dictionaryToArray(creaturesDictionary); * * // creaturesArray will be: * // [{id: 1, type: 'cat'}, {id: 2, type: 'dog'}, {id: 3, type: 'parrot'}]; * * @example * // Usage with RxState * * export class ListComponent { * readonly removeName$ = new Subject(); * * constructor( * private state: RxState, * private api: ApiService * ) { * // Reactive implementation * state.connect( * 'creatures', * this.api.creaturesDictionary$, * (_, creatures) => { * return dictionaryToArray(creatures); * } * ); * } * * // Imperative implementation * convertToArray(): void { * this.api.creaturesDictionary$.pipe( * // subscription handling logic * ).subscribe( * dictionary => this.state.set({creatures: dictionaryToArray(dictionary)}) * ); * } * } * * @returns T[]; * * @docsPage dictionaryToArray * @docsCategory transformation-helpers */ declare function dictionaryToArray(dictionary: { [key: string]: T; }): T[]; /** * @description * Merges an object of type T with updates of type Partial. * Returns a new object where updates override original values while not mutating the original one. * @example * interface Creature { * id: number, * type: string, * name: string * } * * const cat = {id: 1, type: 'cat'}; * * const catWithname = patch(cat, {name: 'Fluffy'}); * * // catWithname will be: * // {id: 1, type: 'cat', name: 'Fluffy'}; * * @example * // Usage with RxState * * export class ProfileComponent { * * readonly changeName$ = new Subject(); * * constructor(private state: RxState) { * // Reactive implementation * state.connect( * this.changeName$, * (state, name) => { * return patch(state, { name }); * } * ); * } * * // Imperative implementation * changeName(name: string): void { * this.state.set(patch(this.state.get(), { name })); * } * } * * @returns T * * @docsPage patch * @docsCategory transformation-helpers */ declare function patch(object: T, upd: Partial): T; /** * @description * Accepts an object of type T, key of type K extends keyof T, and value of type T[K]. * Sets the property and returns a newly updated shallow copy of an object while not mutating the original one. * * @example * * const cat = {id: 1, type: 'cat', name: 'Fluffy'}; * * const renamedCat = setProp(cat, 'name', 'Bella'); * * // renamedCat will be: * // {id: 1, type: 'cat', name: 'Bella'}; * * @example * // Usage with RxState * * export class ProfileComponent { * * readonly changeName$ = new Subject(); * * constructor(private state: RxState) { * // Reactive implementation * state.connect( * this.changeName$, * (state, name) => { * return setProp(state, 'name', name); * } * ); * } * * // Imperative implementation * changeName(name: string): void { * this.state.set(setProp(this.state.get(), 'name', name)); * } * } * * @returns T * * @docsPage setProp * @docsCategory transformation-helpers */ declare function setProp(object: T, key: K, value: T[K]): T; /** * @description * Accepts an object of type T and single key or array of keys (K extends keyof T). * Constructs new object based on provided keys. * * @example * * const cat = {id: 1, type: 'cat', name: 'Fluffy'}; * * const catWithoutType = slice(cat, ['name', 'id']); * * // catWithoutType will be: * // {id: 1, name: 'Fluffy'}; * * @example * // Usage with RxState * * export class AnimalsListComponent { * * constructor(private state: RxState, private api: ApiService) { * state.connect( * 'animals', * this.api.getAnimals(), * (state, animals) => { * return animals.map(animal => slice(animal, ['id', 'name'])); * } * ); * } * } * * @returns T * * @docsPage slice * @docsCategory transformation-helpers */ declare function slice(object: T, keys: K | K[]): Pick; /** * @description * Toggles a boolean property in the object. * Accepts object of type T and key value of which is boolean. * Toggles the property and returns a shallow copy of an object, while not mutating the original one. * * @example * * const state = {items: [1,2,3], loading: true}; * * const updatedState = toggle(state, 'loading'); * * // updatedState will be: * // {items: [1,2,3], loading: false}; * * @example * // Usage with RxState * * export class ListComponent { * readonly loadingChange$ = new Subject(); * * constructor( * private state: RxState * ) { * // Reactive implementation * state.connect( * this.loadingChange$, * (state, _) => { * return toggle(state, 'isLoading'); * } * ); * } * * // Imperative implementation * toggleLoading(): void { * this.state.set(toggle(this.state.get(), 'isLoading')); * } * } * * @returns T * * @docsPage toggle * @docsCategory transformation-helpers */ declare function toggle(object: T, key: OnlyKeysOfSpecificType): T; export { deleteProp, dictionaryToArray, extract, insert, patch, remove, setProp, slice, toDictionary, toggle, update, upsert }; export type { ComparableData };