bsky-app/src/lib/functions.ts

99 lines
2.3 KiB
TypeScript
Raw Normal View History

export function choose<U, T extends Record<string, U>>(
value: keyof T,
choices: T,
): U {
return choices[value]
}
export function dedupArray<T>(arr: T[]): T[] {
const s = new Set(arr)
return [...s]
}
/**
* Taken from @tanstack/query-core utils.ts
* Modified to support Date object comparisons
*
* This function returns `a` if `b` is deeply equal.
* If not, it will replace any deeply equal children of `b` with those of `a`.
* This can be used for structural sharing between JSON values for example.
*/
export function replaceEqualDeep(a: any, b: any): any {
if (a === b) {
return a
}
if (a instanceof Date && b instanceof Date) {
return a.getTime() === b.getTime() ? a : b
}
const array = isPlainArray(a) && isPlainArray(b)
if (array || (isPlainObject(a) && isPlainObject(b))) {
const aItems = array ? a : Object.keys(a)
const aSize = aItems.length
const bItems = array ? b : Object.keys(b)
const bSize = bItems.length
const copy: any = array ? [] : {}
let equalItems = 0
for (let i = 0; i < bSize; i++) {
const key = array ? i : bItems[i]
if (
!array &&
a[key] === undefined &&
b[key] === undefined &&
aItems.includes(key)
) {
copy[key] = undefined
equalItems++
} else {
copy[key] = replaceEqualDeep(a[key], b[key])
if (copy[key] === a[key] && a[key] !== undefined) {
equalItems++
}
}
}
return aSize === bSize && equalItems === aSize ? a : copy
}
return b
}
export function isPlainArray(value: unknown) {
return Array.isArray(value) && value.length === Object.keys(value).length
}
// Copied from: https://github.com/jonschlinkert/is-plain-object
export function isPlainObject(o: any): o is Object {
if (!hasObjectPrototype(o)) {
return false
}
// If has no constructor
const ctor = o.constructor
if (ctor === undefined) {
return true
}
// If has modified prototype
const prot = ctor.prototype
if (!hasObjectPrototype(prot)) {
return false
}
// If constructor does not have an Object-specific method
if (!prot.hasOwnProperty('isPrototypeOf')) {
return false
}
// Most likely a plain Object
return true
}
function hasObjectPrototype(o: any): boolean {
return Object.prototype.toString.call(o) === '[object Object]'
}