toggle
The toggle utility either adds or removes an item from an array depending on whether it already exists, making it ideal for selection UIs, tag pickers, and toggleable lists.
Source Code
View Source Code
ts
import type { Primitive } from '../types';
/**
* Either adds or removes an item from an array, based on whether it already
* exists in the array (toggle behaviour).
*
* @example
* ```ts
* toggle([1, 2, 3], 4) // [1, 2, 3, 4]
* toggle([1, 2, 3], 2) // [1, 3]
*
* toggle(
* [{ id: 1 }, { id: 2 }],
* { id: 3 },
* (obj) => obj.id,
* { strategy: 'prepend' }
* ) // [{ id: 3 }, { id: 1 }, { id: 2 }]
* ```
*
* @param array - The array to modify.
* @param item - The item to add or remove.
* @param selector - A function to determine item identity.
* @param [options] - Options for the toggle operation.
* @param [options.strategy] - Where to insert when adding: 'prepend' or 'append' (default).
* @returns A new array with the item toggled.
*/
export function toggle<T>(
array: T[],
item: T,
selector?: (item: T) => Primitive,
options: { strategy?: 'prepend' | 'append' } = {},
): T[] {
const { strategy = 'append' } = options;
const compareFn = selector ? (el: T) => selector(el) === selector(item) : (el: T) => el === item;
const index = array.findIndex(compareFn);
if (index !== -1) {
return [...array.slice(0, index), ...array.slice(index + 1)];
}
return strategy === 'prepend' ? [item, ...array] : [...array, item];
}Features
- Immutable: Returns a new array; never mutates the original.
- Primitive or object: Works with primitives by default, or objects via a selector.
- Prepend or append: Control insertion position with the
strategyoption.
API
ts
function toggle<T>(
array: T[],
item: T,
selector?: (item: T) => Primitive,
options?: { strategy?: 'prepend' | 'append' },
): T[];Parameters
array: The source array.item: The item to add or remove.selector: Optional function to derive a comparable identity (for objects).options.strategy: Where to insert when adding —'append'(default) or'prepend'.
Returns
- A new array with the item added or removed.
Examples
Toggle Primitives
ts
import { toggle } from '@vielzeug/toolkit';
toggle([1, 2, 3], 4); // [1, 2, 3, 4] — added
toggle([1, 2, 3], 2); // [1, 3] — removedToggle Objects with Selector
ts
import { toggle } from '@vielzeug/toolkit';
const selected = [{ id: 1 }, { id: 2 }];
// Add a new item
toggle(selected, { id: 3 }, (o) => o.id);
// [{ id: 1 }, { id: 2 }, { id: 3 }]
// Remove an existing item
toggle(selected, { id: 1 }, (o) => o.id);
// [{ id: 2 }]Prepend Strategy
ts
import { toggle } from '@vielzeug/toolkit';
toggle([1, 2, 3], 4, undefined, { strategy: 'prepend' });
// [4, 1, 2, 3]Tag Picker UI
ts
import { toggle } from '@vielzeug/toolkit';
import { useState } from 'react';
function TagPicker({ allTags }: { allTags: string[] }) {
const [selected, setSelected] = useState<string[]>([]);
return allTags.map((tag) => (
<button
key={tag}
onClick={() => setSelected((prev) => toggle(prev, tag))}
style={{ fontWeight: selected.includes(tag) ? 'bold' : 'normal' }}
>
{tag}
</button>
));
}