99 lines
2.3 KiB
TypeScript
99 lines
2.3 KiB
TypeScript
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]'
|
|
}
|