У TypeScript існує кілька способів описувати об’єкти: за допомогою інтерфейсів, типів, класів або простих об’єктних літералів. Також окрім цих підходів, є ще вбудований базовий тип – object.

У цьому дописі ми розберемо:

  • що саме означає тип object
  • чим він відрізняється від інших способів опису об’єктів
  • коли його варто застосовувати на практиці

Що таке object?

Тип object у TypeScript представляє всі значення, які не є примітивами.

До примітивних типів у JavaScript належать: string, number, boolean, bigint, symbol, null, undefined.

Приклади значень, які підпадають під тип object:

let a: object;

a = { name: 'Alex' }; // ok
a = [1, 2, 3]; // ok
a = new Date(); // ok

a = 'hello'; // Error: Type 'string' is not assignable to type 'object'
a = 42; // Error: Type 'number' is not assignable to type 'object'

Таким чином, object – це узагальнюючий тип для всіх непримітивних значень у JavaScript.

Важливі відмінності

1. object vs {}

Тип object дозволяє лише непримітивні значення, тоді як {} (порожній об’єктний тип) – дозволяє будь-що, окрім null і undefined:

let x: {};
x = 10; // ok
x = 'text'; // ok
x = { a: 1 }; // ok

let y: object;
y = 10; // error
y = { a: 1 }; // ok

Тобто {} у TypeScript фактично означає «будь-яке значення, крім null та undefined», тоді як object – лише «непримітиви».

2. object vs Object

Тип object було введено у TypeScript 2.2 саме для точнішого опису непримітивних значень. Натомість Object (з великої літери) – це глобальний тип JavaScript, який охоплює навіть примітиви, оскільки в JS кожен примітив може бути обгорнутий у об’єкт (наприклад, new String('abc')):

let a: Object;
a = 42; // ok
a = 'hello'; // ok
a = { key: 1 }; // ok

let b: object;
b = 42; // error
b = { key: 1 }; // ok

На практиці краще використовувати object, оскільки він обмежує тип лише непримітивами і запобігає помилкам типізації. Тип Object менш строгий і зазвичай не потрібен.

3. object vs Record<string, unknown>

Тип object не дозволяє звертатись до властивостей без додаткової перевірки або кастингу. Якщо потрібно явно описати «об’єкт з довільними ключами», краще використовувати Record<string, unknown>:

let obj: object = { name: 'Alex' };

console.log(obj.name); // Error: Property 'name' does not exist on type 'object'

// потрібен кастинг (type assertion)
console.log((obj as { name: string }).name);

Натомість Record<string, unknown> дозволяє звертатись до властивостей, але змушує уточнювати тип значення:

let record: Record<string, unknown> = { name: 'Alex' };

// Можна звернутися до властивості але треба уточнювати тип
console.log(record['name'].toUpperCase()); // Error: Object is of type 'unknown'

// потрібна перевірка типу
if (typeof record['name'] === 'string') {
  console.log(record['name'].toUpperCase());
}

Таким чином:

  • object – це будь-який не примітив, але структура невідома
  • Record<string, unknown> – це об’єкт з рядковими ключами, доступними для звернення, але тип значень потрібно уточнювати

Практичні випадки використання

Тип object застосовують у ситуаціях, коли потрібно працювати з будь-якими непримітивними значеннями, але точна структура об’єкта не має значення. Це зручно, якщо функція або змінна мають приймати будь-який об’єктоподібний тип (наприклад, Object, Array, Map, Date тощо).

Приклад:

function logObject(value: object) {
  console.log('Got object:', value);
}

logObject([1, 2, 3]); // ok
logObject({ a: 1, b: 2 }); // ok
logObject(new Date()); // ok

logObject('hello'); // error
logObject(42); // error

Підсумок

Тип object у TypeScript корисний тоді, коли потрібно відсіяти примітиви, при цьому точна форма об’єкта не має значення.

Якщо ж потрібно описати об’єкти з певними властивостями або ключами, краще використовувати більш точні типи – інтерфейси, власні типи або Record.


Мітки: