Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

To remove duplicate records, first choose the property or properties that define a duplicate. For a unique id, track IDs in a Set and use filter() to keep the first object for each ID. A plain new Set(objects) only removes repeated references to the same object; it does not merge separately created objects with identical fields.

Choose what counts as a duplicate

Two objects can have the same data and still be different objects in JavaScript. Decide whether records are duplicates because they share one field, a combination of fields, or the exact same object reference. Also decide whether to keep the first or last record when keys repeat.

  • One field: records with the same id are duplicates.
  • Several fields: a pair such as accountId and itemId jointly identifies a record.
  • Reference identity: only repeated references to the same object count as duplicates.

Keep the first object for each key

Use a Set of keys alongside filter(). The first object with each key passes the filter; later objects with that key are excluded.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
function uniqueBy<T, K extends keyof T>(items: T[], key: K): T[] {
  const seen = new Set<T[K]>();
  return items.filter((item) => {
    const value = item[key];
    if (seen.has(value)) return false;
    seen.add(value);
    return true;
  });
}

const users = [
  { id: 1, name: "Ada" },
  { id: 1, name: "Ada Lovelace" },
  { id: 2, name: "Grace" },
];

const uniqueUsers = uniqueBy(users, "id");
// [{ id: 1, name: "Ada" }, { id: 2, name: "Grace" }]

The helper retains the first matching record in input order and returns a new shallow array; it does not mutate items. MDN documents that filter() returns a shallow copy containing the elements whose callback returns a truthy value. A Set uses SameValueZero equality for values and reference identity for objects. Its average access must be sublinear under the specification, but implementation details vary, so avoid promising a strict O(1) lookup.

Keep the last object for each key

If the newest record should replace earlier records with the same key, store each object in a Map keyed by that value. A later set() for an existing key replaces its mapped value.

function uniqueByLast<T, K extends keyof T>(items: T[], key: K): T[] {
  const byKey = new Map<T[K], T>();
  for (const item of items) byKey.set(item[key], item);
  return [...byKey.values()];
}

The returned values follow the Map’s key insertion order. Updating an existing key replaces its value but does not by itself move that key to the end, so this is not necessarily the order of the last occurrences. See MDN’s Map reference for its ordering behavior.

Rank #2
TypeScript Programming Language - Software Engineer & Coder T-Shirt
  • TypeScript implements a superset of syntax for strictly typed development, facilitating deep static analysis and enhanced development environment integration. The compiler translates source into standard script formats, ensuring parity across any runtime.
  • TypeScript is ideal for front-end developers, full-stack engineers, and software architects who build large-scale web applications. It serves those looking to improve code excellence, reduce bugs through static checking, and maintain complex projects more.
  • Lightweight, Classic fit, Double-needle sleeve and bottom hem

Deduplicate by a combination of fields

When identity depends on multiple JSON-safe primitive values, serialize a tuple of those fields as the key:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const seen = new Set<string>();
const result = rows.filter((row) => {
  const composite = JSON.stringify([row.accountId, row.itemId]);
  if (seen.has(composite)) return false;
  seen.add(composite);
  return true;
});

Use this only when the selected values have well-defined serialization for your data. JSON serialization is not a universal deep-equality rule: it can omit or transform values, and serialization behavior may depend on object property order. Simple delimiter concatenation can also collide when values contain the delimiter. Define the key according to the identity rules of your application.

Why new Set(objects) usually does not work

For example, new Set([{ id: 1 }, { id: 1 }]) retains both objects. Each object literal creates a separate reference, and Set does not compare object contents. A Set of objects is appropriate only when duplicates mean repeated references to the exact same object; for record identity, store the identifying field in the Set instead.

Handle missing keys and type safety

The generic helper constrains key to a property of T and types the Set values as T[K]. This helps catch an invalid property name at compile time, but the runtime Set and filter logic—not the type annotation—perform deduplication. TypeScript’s mapped types documentation covers compile-time key transformations; those type-level features do not filter array values.

If the chosen property can be absent or nullable, define whether those records should collapse together. With the basic helper, every missing property evaluates to undefined, so only the first such record remains. Add a guard or normalize the key if that does not match your data rules. Set also treats NaN values as equal and treats 0 and -0 as equal.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Select the approach that matches your rule

Requirement Approach Result
Keep the first record for each single key filter() with a Set of key values Retains first-seen records in their input order
Keep the last record’s contents for each key Map keyed by the selected property Later values replace earlier ones; key order remains based on first insertion
Identity depends on multiple fields Composite key, or nested maps Uses the application’s explicit multi-field rule
Only repeated references count Set of objects Removes repeated references, not separate objects with matching fields

A callback that searches earlier elements with indexOf() or findIndex() can be readable for small arrays, but it repeatedly scans prior records. For the common first-record-by-key rule, the Set-and-filter helper expresses both the identity test and retention policy directly.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.