[v5] Rewrite shallow to support iterables (#2427)

This commit is contained in:
Daishi Kato 2024-03-23 13:01:10 +09:00 committed by GitHub
parent bfbbaccfa0
commit 4ac0950e71
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 46 additions and 18 deletions

View File

@ -1,4 +1,22 @@
export function shallow<T>(objA: T, objB: T) {
const isIterable = (obj: object): obj is Iterable<unknown> =>
Symbol.iterator in obj
const compareMapLike = (
iterableA: Iterable<[unknown, unknown]>,
iterableB: Iterable<[unknown, unknown]>,
) => {
const mapA = iterableA instanceof Map ? iterableA : new Map(iterableA)
const mapB = iterableB instanceof Map ? iterableB : new Map(iterableB)
if (mapA.size !== mapB.size) return false
for (const [key, value] of mapA) {
if (!Object.is(value, mapB.get(key))) {
return false
}
}
return true
}
export function shallow<T>(objA: T, objB: T): boolean {
if (Object.is(objA, objB)) {
return true
}
@ -11,26 +29,30 @@ export function shallow<T>(objA: T, objB: T) {
return false
}
if (objA instanceof Map && objB instanceof Map) {
if (objA.size !== objB.size) return false
for (const [key, value] of objA) {
if (!Object.is(value, objB.get(key))) {
if (isIterable(objA) && isIterable(objB)) {
const iteratorA = objA[Symbol.iterator]()
const iteratorB = objB[Symbol.iterator]()
let nextA = iteratorA.next()
let nextB = iteratorB.next()
if (
Array.isArray(nextA.value) &&
Array.isArray(nextB.value) &&
nextA.value.length === 2 &&
nextB.value.length === 2
) {
return compareMapLike(
objA as Iterable<[unknown, unknown]>,
objB as Iterable<[unknown, unknown]>,
)
}
while (!nextA.done && !nextB.done) {
if (!Object.is(nextA.value, nextB.value)) {
return false
}
nextA = iteratorA.next()
nextB = iteratorB.next()
}
return true
}
if (objA instanceof Set && objB instanceof Set) {
if (objA.size !== objB.size) return false
for (const value of objA) {
if (!objB.has(value)) {
return false
}
}
return true
return !!nextA.done && !!nextB.done
}
const keysA = Object.keys(objA)

View File

@ -91,6 +91,12 @@ describe('shallow', () => {
expect(shallow(firstFnCompare, secondFnCompare)).toBe(false)
})
it('compares URLSearchParams', () => {
const a = new URLSearchParams({ hello: 'world' })
const b = new URLSearchParams({ zustand: 'shallow' })
expect(shallow(a, b)).toBe(false)
})
})
describe('unsupported cases', () => {