Будет ли равны объекты по equals() после процесса сериализации/десериализации

Ответ

Ответ не найден

Ответ 18+ 🔞

Вот, представляешь, сижу я тут, разбираю одну дичь с типами в TypeScript. Ну, знаешь, такая классика: у тебя есть интерфейс, а потом ты пытаешься создать объект, который ему якобы соответствует. И тут начинается ёперный театр.

Смотри, объявляю я, например, такой интерфейс, простой, как три копейки:

interface Person {
    name: string;
    age: number;
}

Думаешь, что тут сложного? Ага, щас. Беру и создаю объект-литерал прямо в месте, где Person ожидается:

const vasya: Person = {
    name: "Вася",
    age: 30,
    city: "Москва" // ОШИБКА! Лишнее свойство 'city'.
};

И тут компилятор такой: "Э, сабака сука, стопэ! Ты куда это city приплел? В интерфейсе такого нет!". И он прав, блядь. Это называется excess property checking — проверка на лишние свойства. Работает она, когда ты объектный литерал пишешь прямо в присваивании к переменной с типом или в аргумент функции. Защита, типа, от опечаток, чтобы ты nmae вместо name не написал по пьяни.

Но жизнь, она же хитрая жопа. Вот смотри другой случай:

const obj = {
    name: "Вася",
    age: 30,
    city: "Москва"
};
const vasya: Person = obj; // Всё ок! Никаких ошибок.

Во! Удивление пиздец! Тут уже нет ошибки. Потому что obj — это уже существующая переменная, у неё выведен свой собственный тип { name: string; age: number; city: string; }. И TypeScript проверяет: ага, у obj есть ВСЕ обязательные свойства из Person (name и age)? Есть. Ну и хуй с горы, значит, присваивать можно. Лишнее свойство city просто проигнорируется в контексте типа Person. Главное, чтобы обязательное было.

Это как если бы тебе для пропуска в здание нужны были только бейдж и паспорт. Если ты прямо на проходной начинаешь выкладывать из портфеля ещё и бутерброд, термос и зарядку — тебя остановят: "Мужик, чё несёшь?". А если ты эти вещи уже пронёс внутри рюкзака, а на столе показываешь только нужные документы — тебя пропустят. Рюкзак внутри — это и есть структурная типизация TypeScript, она похуй на лишнее, лишь бы нужное было.

Ну и самый смак, когда это в функции используется. Объявляю функцию:

function greet(person: Person) {
    console.log(`Привет, ${person.name}!`);
}

Если вызвать с литералом — опять заругается на лишние поля:

greet({ name: "Маша", age: 25, city: "Питер" }); // Ошибка!

А если сначала в переменную — то всё заебись:

const masha = { name: "Маша", age: 25, city: "Питер" };
greet(masha); // Всё работает!

Вот такая, блядь, мудя. Кажется, что нелогично, но если вдуматься — в этом есть своя суровая правда. Прямой литерал — это как бы "заявление о намерениях", и его проверяют строго. А переменная — это уже свершившийся факт, объект, который живёт своей жизнью, и система доверяет, что ты знаешь, что делаешь. Доверия ебать ноль к свежесозданному литералу, но чуть больше — к уже существующей сущности.

Так что запомни: хочешь, чтобы тебя не дёргали по мелочам — создавай объект отдельно, а потом уже передавай куда надо с утверждением типа. А если пишешь наскоро и прямо в вызов функции — будь добр, соответствуй интерфейсу буквально, без самодеятельности. И тогда не будет тебе ни хиросимы, ни нагерсраков в виде неожиданных ошибок компиляции.