Skip to content

Instantly share code, notes, and snippets.

@patroza
Last active April 12, 2021 20:52
Show Gist options
  • Save patroza/b335512d74f62ef4fb2ded70bfeb7285 to your computer and use it in GitHub Desktop.
Save patroza/b335512d74f62ef4fb2ded70bfeb7285 to your computer and use it in GitHub Desktop.
/**
*
const something = {}
assert.strictEqual(shallowEqual({ a: O.none }, { a: O.none }), true)
assert.strictEqual(shallowEqual({ a: O.some(1)}, { a: O.some(1) }), true)
assert.strictEqual(shallowEqual({ a: O.some(something)}, { a: O.some(something) }), true)
assert.strictEqual(shallowEqual({ a: O.some(something)}, { a: O.none }), false)
assert.strictEqual(shallowEqual({ a: E.left(something)}, { a: E.left(something) }), true)
assert.strictEqual(shallowEqual({ a: E.right(something)}, { a: E.left(something) }), false)
assert.strictEqual(shallowEqual({ a: E.left(1)}, { a: E.left(2) }), false)
assert.strictEqual(shallowEqual({ a: E.right(1)}, { a: E.right(2) }), false)
// Works by default
assert.strictEqual(shallowEqual(1, 1), true)
assert.strictEqual(shallowEqual(1, 0), false)
assert.strictEqual(shallowEqual(O.none, O.none), true)
assert.strictEqual(shallowEqual(O.some(something), O.some(something)), true)
assert.strictEqual(shallowEqual(O.some(something), O.none), false)
assert.strictEqual(shallowEqual(E.left(something), E.left(something)), true)
assert.strictEqual(shallowEqual(E.right(something), E.left(something)), false)
assert.strictEqual(shallowEqual(E.left(1), E.left(2)), false)
assert.strictEqual(shallowEqual(E.right(1), E.right(2)), false)
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function shallowEqual(objA: any, objB: any) {
if (Object.is(objA, objB)) {
return true
}
if (
typeof objA !== "object" ||
objA === null ||
typeof objB !== "object" ||
objB === null
) {
return false
}
const keysA = Object.keys(objA)
const keysB = Object.keys(objB)
if (keysA.length !== keysB.length) {
return false
}
// Test for A's keys different from B.
for (let i = 0; i < keysA.length; i++) {
const propA = objA[keysA[i]]
const propB = objB[keysA[i]]
if (!Object.hasOwnProperty.call(objB, keysA[i])) {
return false
}
if (!Object.is(propA, propB)) {
if (
typeof propA !== "object" ||
typeof propB !== "object" ||
propA === null ||
propB === null ||
!propA._tag ||
propA._tag !== propB._tag
) {
return false
}
if (
O.isNone(propA) ||
(O.isSome(propA) && Object.is(propA.value, propB.value)) ||
(E.isLeft(propA) && Object.is(propA.left, propB.left)) ||
(E.isRight(propA) && Object.is(propA.right, propB.right))
) {
return true
}
return false
}
}
return true
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function memo<T extends React.ComponentType<any>>(f: T) {
return React.memo(f, shallowEqual)
}
export function useEffect(effect: React.EffectCallback, deps: React.DependencyList) {
// eslint-disable-next-line react-hooks/exhaustive-deps
return React.useEffect(effect, mapDeps(deps))
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function useCallback<T extends (...args: any[]) => any>(
callback: T,
deps: React.DependencyList
) {
// eslint-disable-next-line react-hooks/exhaustive-deps
return React.useCallback(callback, mapDeps(deps))
}
export function useMemo<T>(factory: () => T, deps: React.DependencyList) {
// eslint-disable-next-line react-hooks/exhaustive-deps
return React.useMemo(factory, mapDeps(deps))
}
function mapDeps(deps: React.DependencyList) {
return deps.map(convertDep)
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function convertDep(x: any) {
return typeof x !== "object" || x === null
? x
: O.isSome(x) || O.isNone(x)
? O.toNullable(x)
: E.isLeft(x)
? x.left
: E.isRight(x)
? x.right
: x
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment