Published on

Gestionar colecciones únicas con Set en JavaScript

Authors

¡Hola! Hoy quiero compartir cómo y cuándo usar el objeto Set en JavaScript. Aunque ya hayas usado Array, quizá te preguntes en qué casos Set aporta ventajas, o cómo manejarlo correctamente en React con TypeScript.


Introducción

¿Te has encontrado gestionando etiquetas o datos que no deben repetirse y terminas usando filter o includes para evitar duplicados? Esto puede complicar el código y afectar el rendimiento.

1. Planteamiento del problema: frustración por elementos duplicados

Por ejemplo, al registrar etiquetas seleccionadas por el usuario:

const selectedTags = ['react', 'typescript', 'react']

Los duplicados generan más lógica para filtrar y verificar, entorpeciendo el flujo.

2. Duda general: ¿solo arreglos?

Los arreglos son útiles para mantener orden, pero:

  • Mantener unicidad requiere lógica adicional.
  • Verificar existencia es O(n).
  • Podrías enfrentar problemas de rendimiento con muchos elementos.

3. Empatía: la necesidad de colecciones únicas

“Quiero evitar duplicados”, “necesito verificar rápido si existe un elemento”… Son casos comunes donde una colección única simplificaría todo.

4. Propuesta: usar Set

4.1 Conceptos básicos de Set

const nums = new Set<number>()
nums.add(1)
nums.add(2)
nums.add(2) // Se ignora el duplicado
console.log(nums.has(1)) // true
console.log(nums.size) // 2
nums.delete(1)
console.log(nums.size) // 1
nums.clear()
console.log(nums.size) // 0
  • new Set<T>(iterable?): acepta un iterable para iniciar.
  • .add(value): añade un elemento.
  • .has(value): comprueba existencia.
  • .delete(value): elimina un elemento.
  • .size: cantidad de elementos.
  • .clear(): vacía el conjunto.

4.2 Iteración

const fruits = new Set(['apple', 'banana', 'apple'])
for (const f of fruits) {
  console.log(f)
}
// apple
// banana

Set implementa Symbol.iterator, por lo que es iterable con for...of. La iteración respeta el orden de inserción, facilitando recorrer la colección de forma sencilla para renderizar listas o procesar cada elemento.

4.3 Conversión entre Set y Array

const arr = [1, 2, 2, 3]
const uniqueArr = [...new Set(arr)] // [1, 2, 3]

Utilizar el operador spread (...) o Array.from() permite convertir un Set en un arreglo de forma rápida. Esto simplifica la obtención de un nuevo arreglo sin duplicados a partir de uno existente.

5. Ejemplo en React + TypeScript

Al usar Set en el estado de React, evita mutar directamente previniendo re-renderizados. Crea siempre un nuevo Set:

import React, { useState } from 'react'

export const TagSelector: React.FC = () => {
  const [selectedTags, setSelectedTags] = useState<Set<string>>(new Set())

  const toggleTag = (tag: string) => {
    setSelectedTags((prev) => {
      const next = new Set(prev)
      if (next.has(tag)) {
        next.delete(tag)
      } else {
        next.add(tag)
      }
      return next
    })
  }

  return (
    <div>
      {['react', 'typescript', 'css', 'html'].map((tag) => (
        <button
          key={tag}
          onClick={() => toggleTag(tag)}
          style={{
            margin: '4px',
            background: selectedTags.has(tag) ? '#FAAB15' : '#eee',
          }}
        >
          {tag}
        </button>
      ))}
      <p>Etiquetas seleccionadas: {[...selectedTags].join(', ') || 'ninguna'}</p>
    </div>
  )
}

6. Conclusión: disfruta gestionar colecciones ligeras

  • No solo arreglos: para unicidad, Set es ideal.
  • TypeScript seguro: Set<T> define el tipo de elementos.
  • React amigable: al devolver un nuevo Set, React detecta cambios y re-renderiza.

Con Set, gestionar colecciones únicas es rápido, limpio y eficiente. ¡Pruébalo en tu próximo proyecto!