Skip to content

Instantly share code, notes, and snippets.

@vbfox
Created January 15, 2021 16:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vbfox/2cf6dc6833aa3fcf3483012731268c5a to your computer and use it in GitHub Desktop.
Save vbfox/2cf6dc6833aa3fcf3483012731268c5a to your computer and use it in GitHub Desktop.
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
function deepReferentialEquality(from: any, to: any, path = ''): any {
if (to === undefined || from === undefined || to === null || from === null) {
return to;
}
const objectType = typeof from;
if (objectType !== typeof to) {
// The object changed type
return to;
}
if (from === to) {
// Same type so either it's the same object reference or the same primitive value
return from;
}
function isPlainObject(o: any) {
return Object.prototype.isPrototypeOf.call(Object.getPrototypeOf(o), Object);
}
if (objectType === 'object') {
if (isPlainObject(to) && isPlainObject(from)) {
let canReturnFrom = true;
let canReturnTo = true;
const toKeys = Object.keys(to);
const result: any = {};
for (const key of toKeys) {
const finalValue = deepReferentialEquality(from[key], to[key], `${path}.${key}`);
result[key] = finalValue;
if (finalValue !== to) {
canReturnTo = false;
}
if (finalValue !== from) {
canReturnFrom = false;
}
}
if (canReturnTo) {
return to;
}
if (canReturnFrom) {
// Assume from has no extra keys or we don't care
return from;
}
return result;
}
if (Array.isArray(to) && Array.isArray(from)) {
let canReturnFrom = to.length === from.length;
let canReturnTo = true;
const result: any[] = [];
// eslint-disable-next-line
for (const i in to) {
const finalValue: any = deepReferentialEquality(from[i], to[i], `${path}[${i}]`);
result[i] = finalValue;
if (finalValue !== to) {
canReturnTo = false;
}
if (finalValue !== from) {
canReturnFrom = false;
}
}
if (canReturnTo) {
return to;
}
if (canReturnFrom) {
return from;
}
return result;
}
}
// We don't optimize that type
return to;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment