Ответ
Ответ не найден
Ответ 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); // Всё работает!
Вот такая, блядь, мудя. Кажется, что нелогично, но если вдуматься — в этом есть своя суровая правда. Прямой литерал — это как бы "заявление о намерениях", и его проверяют строго. А переменная — это уже свершившийся факт, объект, который живёт своей жизнью, и система доверяет, что ты знаешь, что делаешь. Доверия ебать ноль к свежесозданному литералу, но чуть больше — к уже существующей сущности.
Так что запомни: хочешь, чтобы тебя не дёргали по мелочам — создавай объект отдельно, а потом уже передавай куда надо с утверждением типа. А если пишешь наскоро и прямо в вызов функции — будь добр, соответствуй интерфейсу буквально, без самодеятельности. И тогда не будет тебе ни хиросимы, ни нагерсраков в виде неожиданных ошибок компиляции.