Какие тут есть варианты:
Object.values(Object.fromEntries(arr.map(n => [ n.user.id, n ])))
// или, если в результирующий массив должны попадать те из "одинаковых"
// элементов, что расположены в исходном массиве первыми
Object.values(arr.reduce((acc, n) => (acc[n.user.id] ??= n, acc), {}))
// или, если также надо сохранять взаимное расположение элементов
arr.filter(function({ user: { id: n } }) {
return !(this[n] = this.hasOwnProperty(n));
}, {})
Можно решить задачу и в более общем виде - сделаем генератор, выдающий уникальные значения. Принимает в качестве параметров итерируемый объект и признак, по которому осуществляется уникализация (может быть функцией или именем свойства):
function* unique(data, key = n => n) {
const getKey = key instanceof Function ? key : n => n[key];
const keys = new Set;
for (const n of data) {
const k = getKey(n);
if (!keys.has(k)) {
keys.add(k);
yield n;
}
}
}
Теперь можно делать так (ваш случай):
const result = Array.from(unique(arr, n => n.user.id));
Или так:
''.concat(...unique('ABBACADCACDCEACBAEBA')) // 'ABCDE'
Или так:
// можете открыть консоль и проверить самостоятельно, сколько
// элементов в исходной коллекции, а сколько уникальных
[...unique(document.links, 'href')]