Оператор typeof у JavaScript
typeof це оператор, який під час виконання програми повертає рядок з описом типу значення. У TypeScript ключове слово typeof у позиції типу означає інше: воно на етапі компіляції витягує тип змінної, функції або класу.
Теорія
TL;DR
- У JavaScript
typeofпрацює в runtime і повертає рядок, а не сам тип. - Можливі результати:
"number","string","boolean","undefined","object","function","symbol","bigint". typeof nullдає"object", це відома історична помилка мови.- Масиви технічно є об'єктами, тому
typeof []теж дає"object". typeofдля неоголошеної змінної не кидає помилку: безпечний спосіб перевірити її наявність.- У TypeScript
typeofу позиції типу працює в compile-time і повертає тип.
Швидкий приклад
console.log(typeof 42); // "number"
console.log(typeof 'hello'); // "string"
console.log(typeof true); // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof { a: 1 }); // "object"
console.log(typeof [1, 2, 3]); // "object" (масиви це об'єкти!)
console.log(typeof null); // "object" (історична помилка мови)
console.log(typeof function(){}); // "function"Оператор повертає рядок, а не сам тип.
Особливості результатів typeof
| Ситуація | Результат | Коментар |
|---|---|---|
typeof x (якщо x не оголошена) | "undefined" | Не кидає помилку, це безпечно |
typeof null | "object" | Історична помилка в JS |
typeof [] | "object" | Масиви технічно є об'єктами |
typeof function() {} | "function" | Спеціальний підтип об'єкта |
Головне, що варто запам'ятати: typeof не вміє відрізнити масив від звичайного об'єкта чи від null. Для масива використовують Array.isArray(x), а null перевіряють прямим порівнянням x === null.
Безпечна перевірка наявності змінної
if (typeof user === 'undefined') {
console.log('user is not defined');
}Тут typeof дозволяє перевірити наявність змінної без помилки, навіть якщо вона взагалі не оголошена. Будь-яке інше звертання до неоголошеного ідентифікатора одразу дало б ReferenceError.
typeof у TypeScript
А ось тепер головна відмінність.
У TypeScript
typeofце оператор, що працює з типами на етапі компіляції (compile-time), і він повертає тип, а не рядок.
Тобто він не обчислює значення, а бере тип змінної або виразу, щоб цей тип можна було використати в анотаціях.
const user = {
name: 'Tim',
age: 30
};
// беремо тип об'єкта user
type UserType = typeof user;
// еквівалентно:
type UserType = {
name: string;
age: number;
};На відміну від JavaScript,
typeofтут не виконує код, а просто витягує тип змінної, функції або класу.
typeof разом з ReturnType
function makeUser() {
return { name: 'Alice', active: true };
}
type User = ReturnType<typeof makeUser>;
// User = { name: string; active: boolean }Тут
typeof makeUserдає тип функції, аReturnType<...>дає тип значення, яке ця функція повертає.
Ключові відмінності JS і TS
| Особливість | typeof у JavaScript | typeof у TypeScript |
|---|---|---|
| Коли працює | Під час виконання (runtime) | Під час компіляції (compile-time) |
| Що повертає | Рядок з типом ("number", "object", ...) | Тип змінної, функції або об'єкта |
| Чи можна вживати в умовах | Так | Ні, працює лише в типах |
| Приклад | typeof x === 'string' | type T = typeof x |
Якщо x не оголошена | Помилки немає | Помилка компіляції |
Приклад для контрасту
// JavaScript
let a = 10;
console.log(typeof a); // "number"// TypeScript
let a = 10;
type AType = typeof a; // AType = numberПерший повертає рядок під час виконання, другий створює тип на етапі компіляції.
Типові помилки
- Очікувати
"array"відtypeof []. Такого результату не існує, масив це об'єкт. ВикористовуйтеArray.isArray(value). - Покладатися на
typeof value === 'object'для перевірки об'єкта.nullтеж пройде цю перевірку. Правильно:value !== null && typeof value === 'object'. - Плутати рядок і тип.
typeof xу JS це завжди рядок, томуtypeof x === Numberніколи не буде істиною, требаtypeof x === 'number'. - Думати, що
typeofу TS перевіряє щось у рантаймі. У позиції типу він зникає після компіляції і не впливає на згенерований JavaScript. - Забувати про
typeofяк про єдиний безпечний спосіб торкнутися неоголошеної змінної. Перевіркаif (user === undefined)кинеReferenceError, аif (typeof user === 'undefined')ні.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.