Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Чому TypeScript ловить зайву властивість в об'єкті-літералі, але пропускає її через змінну?

TypeScript перевіряє типи структурно: об'єкт підходить до типу, якщо має всі потрібні властивості потрібних типів. Зайві властивості цьому не заважають.

type Point = { x: number; y: number };

const point3d = { x: 1, y: 2, z: 3 };
const p: Point = point3d;   // ок - є x і y, z просто ігнорується

Але для «свіжого» об'єкта-літерала діє додаткова перевірка зайвих властивостей:

const p: Point = { x: 1, y: 2, z: 3 };
// помилка: Object literal may only specify known properties, and 'z' does not exist in type 'Point'

Чому так. Якщо ви пишете літерал прямо там, де очікується конкретний тип, зайва властивість майже напевно - друкарська помилка або непорозуміння:

createUser({ name: 'Оля', emial: 'olia@example.com' });   // emial замість email - зловлено

Але якщо об'єкт уже існує й має ширшу форму, передати його туди, де потрібна частина полів, - нормальна практика структурної типізації.

Де перевірка зайвих властивостей не спрацьовує:

  • об'єкт спершу присвоєно змінній, а потім передано;
  • результат функції, розгортання ({ ...defaults, extra: 1 } перевіряється, а от { ...obj }, де obj має зайве, - ні);
  • тип має індексну сигнатуру ([key: string]: unknown) - тоді будь-які ключі допустимі;
  • приведення через as.

Пастка з опціональними полями:

type Options = { timeout?: number; retries?: number };

const userOptions = { timeout: 500, retires: 3 };   // друкарська помилка в retries
const options: Options = userOptions;               // жодної помилки! усі поля опціональні

Тип, у якого всі поля необов'язкові («слабкий тип»), TypeScript частково захищає: якщо в об'єкта немає жодного спільного поля з типом ({ timout: 500 }), буде помилка. Але одна правильна властивість поруч з друкарською помилкою - і перевірка мовчить, а retries тихо лишається не заданим.

Що робити: передавати літерали напряму в місця з типом, використовувати satisfies для об'єктів-конфігурацій, а для зовнішніх даних - валідацію під час виконання (Zod), яка може відкидати невідомі ключі (.strict()).

Докладніше в документації: Перевірка зайвих властивостей

Схожі питання