How to Get Unique Values from an Array of Objects in TypeScript

I often need this when building customer dashboards or sales-reporting tools. An API returns several records for the same customer, city, or sales region, but the dropdown or summary card should show each value only once.

TypeScript makes this job safer because you can define the object shape before you write the filtering logic. That prevents simple mistakes, such as using a property name that does not exist in your data.

Below, I will use a small customer reporting utility and show how to get unique values from an array of objects in TypeScript with complete working examples.

What Does Unique Mean in TypeScript?

A unique value appears only once in the final result. With an array of objects, you usually decide uniqueness from one property, such as city, customerId, or email.

For example, a customer dashboard may receive several orders from customers in Austin, Texas. You may want to list Austin once, even though several records use that city.

An interface defines the expected shape of an object. It helps TypeScript identify property spelling errors before you run the program. If you need a refresher, see this guide on creating an object from a TypeScript interface.

This tutorial assumes TypeScript 5+ and Node.js 18+. Create a file named unique-values.ts, then run:

npx ts-node unique-values.ts

You can also compile and run the file:

npx tsc unique-values.ts
node unique-values.js

Here is the customer data used throughout this guide:

interface CustomerOrder {
orderId: number;
customerId: number;
customerName: string;
city: string;
state: string;
total: number;
}

const customerOrders: CustomerOrder[] = [
{
orderId: 1001,
customerId: 1,
customerName: "Emma Johnson",
city: "Austin",
state: "Texas",
total: 245
},
{
orderId: 1002,
customerId: 2,
customerName: "Daniel Miller",
city: "Chicago",
state: "Illinois",
total: 180
},
{
orderId: 1003,
customerId: 3,
customerName: "Olivia Davis",
city: "Austin",
state: "Texas",
total: 320
},
{
orderId: 1004,
customerId: 1,
customerName: "Emma Johnson",
city: "Austin",
state: "Texas",
total: 95
},
{
orderId: 1005,
customerId: 4,
customerName: "Noah Wilson",
city: "Seattle",
state: "Washington",
total: 410
}
];

console.log(customerOrders);

Sample output:

[
{
orderId: 1001,
customerId: 1,
customerName: 'Emma Johnson',
city: 'Austin',
state: 'Texas',
total: 245
},
{
orderId: 1002,
customerId: 2,
customerName: 'Daniel Miller',
city: 'Chicago',
state: 'Illinois',
total: 180
},
...
]

Get Unique Values from an Array of Objects with Set

The simplest way to get unique values from an array of objects in TypeScript is to use a Set.

A Set stores each primitive value only once. A primitive value is a basic value such as a string, number, or boolean. This makes Set ideal when you need unique city names, customer IDs, or state names.

Get unique city names

Use map() to extract city names first. Then pass that new array into Set.

interface CustomerOrder {
orderId: number;
customerId: number;
customerName: string;
city: string;
state: string;
total: number;
}

const customerOrders: CustomerOrder[] = [
{
orderId: 1001,
customerId: 1,
customerName: "Emma Johnson",
city: "Austin",
state: "Texas",
total: 245
},
{
orderId: 1002,
customerId: 2,
customerName: "Daniel Miller",
city: "Chicago",
state: "Illinois",
total: 180
},
{
orderId: 1003,
customerId: 3,
customerName: "Olivia Davis",
city: "Austin",
state: "Texas",
total: 320
},
{
orderId: 1004,
customerId: 1,
customerName: "Emma Johnson",
city: "Austin",
state: "Texas",
total: 95
},
{
orderId: 1005,
customerId: 4,
customerName: "Noah Wilson",
city: "Seattle",
state: "Washington",
total: 410
}
];

const uniqueCities = [...new Set(customerOrders.map((order) => order.city))];

console.log(uniqueCities);

Sample output:

[ 'Austin', 'Chicago', 'Seattle' ]

I executed the above example code and added the screenshot below.

Get Unique Values from an Array of Objects in TypeScript

The map() method creates this intermediate array:

[ 'Austin', 'Chicago', 'Austin', 'Austin', 'Seattle' ]

Set removes repeated strings, and the spread operator converts the Set back into a regular array. This approach works well for dropdown values in a frontend web application or reporting filters in a backend API.

If you want to understand array iteration in more detail, see how to iterate over arrays in TypeScript.

Pro Tip: I use Set first when I only need one primitive field, such as an ID or category. It keeps the code short, readable, and fast enough for most dashboard data.

Get unique customer IDs

The same pattern works with numbers.

interface CustomerOrder {
orderId: number;
customerId: number;
customerName: string;
city: string;
state: string;
total: number;
}

const customerOrders: CustomerOrder[] = [
{
orderId: 1001,
customerId: 1,
customerName: "Emma Johnson",
city: "Austin",
state: "Texas",
total: 245
},
{
orderId: 1002,
customerId: 2,
customerName: "Daniel Miller",
city: "Chicago",
state: "Illinois",
total: 180
},
{
orderId: 1003,
customerId: 3,
customerName: "Olivia Davis",
city: "Austin",
state: "Texas",
total: 320
},
{
orderId: 1004,
customerId: 1,
customerName: "Emma Johnson",
city: "Austin",
state: "Texas",
total: 95
},
{
orderId: 1005,
customerId: 4,
customerName: "Noah Wilson",
city: "Seattle",
state: "Washington",
total: 410
}
];

const uniqueCustomerIds = [...new Set(customerOrders.map((order) => order.customerId))];

console.log(uniqueCustomerIds);
console.log(`Unique customers: ${uniqueCustomerIds.length}`);

Sample output:

[ 1, 2, 3, 4 ]
Unique customers: 4

I executed the above example code and added the screenshot below.

How to Get Unique Values from an Array of Objects in TypeScript

Get Unique Objects by Property with Map

Use a Map when you need the full unique objects, not just a list of property values.

A Map stores key-value pairs. In this example, the customerId becomes the key and the order object becomes the value. Since each key can appear once, Map naturally removes duplicates.

This technique is useful when a Node.js script receives duplicate API data and you need one complete record per customer.

interface CustomerOrder {
orderId: number;
customerId: number;
customerName: string;
city: string;
state: string;
total: number;
}

const customerOrders: CustomerOrder[] = [
{
orderId: 1001,
customerId: 1,
customerName: "Emma Johnson",
city: "Austin",
state: "Texas",
total: 245
},
{
orderId: 1002,
customerId: 2,
customerName: "Daniel Miller",
city: "Chicago",
state: "Illinois",
total: 180
},
{
orderId: 1003,
customerId: 3,
customerName: "Olivia Davis",
city: "Austin",
state: "Texas",
total: 320
},
{
orderId: 1004,
customerId: 1,
customerName: "Emma Johnson",
city: "Austin",
state: "Texas",
total: 95
},
{
orderId: 1005,
customerId: 4,
customerName: "Noah Wilson",
city: "Seattle",
state: "Washington",
total: 410
}
];

const customersById = new Map<number, CustomerOrder>(
customerOrders.map((order) => [order.customerId, order])
);

const uniqueCustomers = [...customersById.values()];

console.log(uniqueCustomers);

Sample output:

[
{
orderId: 1004,
customerId: 1,
customerName: 'Emma Johnson',
city: 'Austin',
state: 'Texas',
total: 95
},
{
orderId: 1002,
customerId: 2,
customerName: 'Daniel Miller',
city: 'Chicago',
state: 'Illinois',
total: 180
},
{
orderId: 1003,
customerId: 3,
customerName: 'Olivia Davis',
city: 'Austin',
state: 'Texas',
total: 320
},
{
orderId: 1005,
customerId: 4,
customerName: 'Noah Wilson',
city: 'Seattle',
state: 'Washington',
total: 410
}
]

Notice that Emma Johnson’s second order remains in the result. Map replaces the earlier value when it finds the same customerId again.

Use this approach when you want the last object for each unique property. For more Map patterns, review how to create a Map from an array in TypeScript.

Keep the first object instead

Sometimes the first record is the one you need. For example, an API collector may process the oldest order first, and you may want to preserve that first occurrence.

Use a loop with Map.has() before inserting a value.

interface CustomerOrder {
orderId: number;
customerId: number;
customerName: string;
city: string;
state: string;
total: number;
}

const customerOrders: CustomerOrder[] = [
{
orderId: 1001,
customerId: 1,
customerName: "Emma Johnson",
city: "Austin",
state: "Texas",
total: 245
},
{
orderId: 1002,
customerId: 2,
customerName: "Daniel Miller",
city: "Chicago",
state: "Illinois",
total: 180
},
{
orderId: 1003,
customerId: 3,
customerName: "Olivia Davis",
city: "Austin",
state: "Texas",
total: 320
},
{
orderId: 1004,
customerId: 1,
customerName: "Emma Johnson",
city: "Austin",
state: "Texas",
total: 95
},
{
orderId: 1005,
customerId: 4,
customerName: "Noah Wilson",
city: "Seattle",
state: "Washington",
total: 410
}
];

const firstCustomerOrderById = new Map<number, CustomerOrder>();

for (const order of customerOrders) {
if (!firstCustomerOrderById.has(order.customerId)) {
firstCustomerOrderById.set(order.customerId, order);
}
}

const uniqueCustomers = [...firstCustomerOrderById.values()];

console.log(uniqueCustomers);

Sample output:

[
{
orderId: 1001,
customerId: 1,
customerName: 'Emma Johnson',
city: 'Austin',
state: 'Texas',
total: 245
},
{
orderId: 1002,
customerId: 2,
customerName: 'Daniel Miller',
city: 'Chicago',
state: 'Illinois',
total: 180
},
{
orderId: 1003,
customerId: 3,
customerName: 'Olivia Davis',
city: 'Austin',
state: 'Texas',
total: 320
},
{
orderId: 1005,
customerId: 4,
customerName: 'Noah Wilson',
city: 'Seattle',
state: 'Washington',
total: 410
}
]

This version preserves order 1001 for Emma Johnson because the code ignores later records with the same customer ID.

Get Unique Values from an Array of Objects with filter()

The filter() method gives you more control when defining duplicates. It works well for smaller arrays or when you need to apply custom logic.

In this version, findIndex() finds the first object with the same customerId. filter() keeps only an object whose current index matches that first index.

interface CustomerOrder {
orderId: number;
customerId: number;
customerName: string;
city: string;
state: string;
total: number;
}

const customerOrders: CustomerOrder[] = [
{
orderId: 1001,
customerId: 1,
customerName: "Emma Johnson",
city: "Austin",
state: "Texas",
total: 245
},
{
orderId: 1002,
customerId: 2,
customerName: "Daniel Miller",
city: "Chicago",
state: "Illinois",
total: 180
},
{
orderId: 1003,
customerId: 3,
customerName: "Olivia Davis",
city: "Austin",
state: "Texas",
total: 320
},
{
orderId: 1004,
customerId: 1,
customerName: "Emma Johnson",
city: "Austin",
state: "Texas",
total: 95
},
{
orderId: 1005,
customerId: 4,
customerName: "Noah Wilson",
city: "Seattle",
state: "Washington",
total: 410
}
];

const uniqueCustomers = customerOrders.filter((order, index, orders) => {
return orders.findIndex(
(currentOrder) => currentOrder.customerId === order.customerId
) === index;
});

console.log(uniqueCustomers);

Sample output:

[
{
orderId: 1001,
customerId: 1,
customerName: 'Emma Johnson',
city: 'Austin',
state: 'Texas',
total: 245
},
{
orderId: 1002,
customerId: 2,
customerName: 'Daniel Miller',
city: 'Chicago',
state: 'Illinois',
total: 180
},
{
orderId: 1003,
customerId: 3,
customerName: 'Olivia Davis',
city: 'Austin',
state: 'Texas',
total: 320
},
{
orderId: 1005,
customerId: 4,
customerName: 'Noah Wilson',
city: 'Seattle',
state: 'Washington',
total: 410
}
]

This keeps the first matching object, just like the previous Map.has() example. Learn more about filtering arrays in TypeScript if you want to combine uniqueness with other business rules.

I avoid this approach for very large arrays. findIndex() may scan the array repeatedly, while Set and Map usually offer a clearer and more efficient solution.

Get Unique Objects by Multiple Properties

Sometimes one field does not identify a unique record. For example, customerName alone may not be enough because two customers can share the same name.

You can create a composite key by combining two properties. Here, the customer name and city together define uniqueness.

interface CustomerOrder {
orderId: number;
customerId: number;
customerName: string;
city: string;
state: string;
total: number;
}

const customerOrders: CustomerOrder[] = [
{
orderId: 1001,
customerId: 1,
customerName: "Emma Johnson",
city: "Austin",
state: "Texas",
total: 245
},
{
orderId: 1002,
customerId: 2,
customerName: "Daniel Miller",
city: "Chicago",
state: "Illinois",
total: 180
},
{
orderId: 1003,
customerId: 3,
customerName: "Emma Johnson",
city: "Austin",
state: "Texas",
total: 320
},
{
orderId: 1004,
customerId: 4,
customerName: "Emma Johnson",
city: "Denver",
state: "Colorado",
total: 95
},
{
orderId: 1005,
customerId: 5,
customerName: "Noah Wilson",
city: "Seattle",
state: "Washington",
total: 410
}
];

const uniqueOrdersByCustomerAndCity = [
...new Map(
customerOrders.map((order) => [
`${order.customerName.toLowerCase()}|${order.city.toLowerCase()}`,
order
])
).values()
];

console.log(uniqueOrdersByCustomerAndCity);

Sample output:

[
{
orderId: 1003,
customerId: 3,
customerName: 'Emma Johnson',
city: 'Austin',
state: 'Texas',
total: 320
},
{
orderId: 1002,
customerId: 2,
customerName: 'Daniel Miller',
city: 'Chicago',
state: 'Illinois',
total: 180
},
{
orderId: 1004,
customerId: 4,
customerName: 'Emma Johnson',
city: 'Denver',
state: 'Colorado',
total: 95
},
{
orderId: 1005,
customerId: 5,
customerName: 'Noah Wilson',
city: 'Seattle',
state: 'Washington',
total: 410
}
]

The toLowerCase() calls make the comparison case-insensitive. Without them, "Austin" and "AUSTIN" would count as different values.

Use a separator that cannot appear in your source values, or serialize a structured key when your data contains unpredictable text. You can also clean API results before deduplicating them with removing undefined values from an array in TypeScript.

Create a Reusable Generic Function

A generic is a TypeScript feature that lets one function work with many data types while preserving type safety. Instead of writing separate functions for customers, products, and employees, you can build one reusable utility.

The function below accepts an array of objects and a property name. It returns unique values from that property.

interface CustomerOrder {
orderId: number;
customerId: number;
customerName: string;
city: string;
state: string;
total: number;
}

function getUniqueValues<T, K extends keyof T>(
items: T[],
key: K
): T[K][] {
return [...new Set(items.map((item) => item[key]))];
}

const customerOrders: CustomerOrder[] = [
{
orderId: 1001,
customerId: 1,
customerName: "Emma Johnson",
city: "Austin",
state: "Texas",
total: 245
},
{
orderId: 1002,
customerId: 2,
customerName: "Daniel Miller",
city: "Chicago",
state: "Illinois",
total: 180
},
{
orderId: 1003,
customerId: 3,
customerName: "Olivia Davis",
city: "Austin",
state: "Texas",
total: 320
},
{
orderId: 1004,
customerId: 4,
customerName: "Noah Wilson",
city: "Seattle",
state: "Washington",
total: 410
}
];

const uniqueCities = getUniqueValues(customerOrders, "city");
const uniqueStates = getUniqueValues(customerOrders, "state");
const uniqueCustomerIds = getUniqueValues(customerOrders, "customerId");

console.log(uniqueCities);
console.log(uniqueStates);
console.log(uniqueCustomerIds);

Sample output:

[ 'Austin', 'Chicago', 'Seattle' ]
[ 'Texas', 'Illinois', 'Washington' ]
[ 1, 2, 3, 4 ]

I executed the above example code and added the screenshot below.

Get Unique Values from an Array of Objects TypeScript

T represents the object type, and K extends keyof T limits the key to valid properties from that object type. That means TypeScript catches this mistake during development:

getUniqueValues(customerOrders, "country");

Because country does not exist in CustomerOrder, TypeScript reports a compile-time error. This is a strong example of why developers use TypeScript for API integrations and data-processing utilities. You can explore related patterns in this guide to generic object types in TypeScript.

Which Approach Should You Use?

Choose the method based on the result you need.

RequirementBest approachWhy
Unique strings or numbersSet with map()Short, clear, and efficient
Full unique objects, keep last itemMapLater records replace earlier records
Full unique objects, keep first itemMap with has()You control duplicate handling
Small dataset with custom rulesfilter() with findIndex()Flexible but less efficient for large arrays
Reuse logic across object typesGeneric function with SetKeeps code type-safe and maintainable
Unique objects from several fieldsMap with a composite keySupports multi-property comparison

For most real-world frontend development and Node.js utilities, I start with Set for a single value and Map for complete objects.

Things to Keep in Mind

  • Objects need a key: new Set(arrayOfObjects) does not remove objects with matching properties because separate objects have different references in memory.
  • Choose the right property: Use a stable ID such as customerId or email when possible. Names and cities often repeat.
  • Decide first versus last: A basic Map keeps the last matching object. Use Map.has() when the first record matters.
  • Handle missing data: Validate API data before accessing a property. Read how to check if an object is undefined in TypeScript when your source may return incomplete values.
  • Avoid any: Define an interface or type for your objects. This protects property access and improves autocomplete. See TypeScript any type for the trade-offs.
  • Use strict mode: Enable "strict": true in tsconfig.json so TypeScript catches null, undefined, and property issues early.

Frequently Asked Questions

How do I remove duplicate objects from an array in TypeScript?

Use a Map keyed by a property that identifies each object, such as id or email. Convert the Map values back into an array with [...map.values()]. Use Map.has() if you want to keep the first duplicate instead of the last.

Can I use Set to remove duplicate objects in TypeScript?

Not directly when two separate objects have identical content. Set compares object references, not every property value. Extract a primitive field with map() or use a Map with a unique key.

How do I get unique values by a property in TypeScript?

Use const values = […new Set(items.map((item) => item.property))]. This extracts the property values and removes duplicates. It works well for strings, numbers, and booleans.

Does Map keep the first or last duplicate in TypeScript?

A Map keeps the last value assigned to a repeated key. Create the Map in a loop and check map.has(key) before calling map.set(key, value) to keep the first object.

How do I find unique objects using two properties in TypeScript?

Create a composite key from the two properties, such as `${item.name}|${item.city}`. Use that value as a Map key. Normalize text with toLowerCase() when your comparison should ignore letter case.

Is filter() slower than Set or Map for unique values?

It often is for large arrays when you combine filter() with findIndex(). Each item may trigger another scan of the array. Prefer Set or Map when processing large API responses or automation data.

Getting unique values from an array of objects in TypeScript becomes simple once you choose whether you need primitive values or complete objects. Start with Set for a property list and Map for object-level deduplication, then add reusable generic helpers when the same pattern appears across your project.

You May Also Like

51 Python Programs

51 PYTHON PROGRAMS PDF FREE

Download a FREE PDF (112 Pages) Containing 51 Useful Python Programs.

pyython developer roadmap

Aspiring to be a Python developer?

Download a FREE PDF on how to become a Python developer.

Let’s be friends

Be the first to know about sales and special discounts.