Пошук уроків, статей та іншого контенту
Навчіться звужувати типи примітивних значень за допомогою оператора typeof.
Звуження типів — це процес, під час якого TypeScript уточнює тип змінної після перевірки.
Наприклад, змінна може мати тип string | number. Поки TypeScript не знає, яке саме значення зберігається у змінній, він дозволяє використовувати лише операції, спільні для обох типів.
function printValue(value: string | number): void {
// Тут value може бути рядком або числом
console.log(value);
}Якщо перевірити тип значення за допомогою typeof, TypeScript зможе звузити тип у відповідній гілці коду.
typeofОператор typeof повертає рядок із назвою типу значення під час виконання програми.
console.log(typeof "hello"); // "string"
console.log(typeof 42); // "number"
console.log(typeof true); // "boolean"
console.log(typeof undefined); // "undefined"Для звуження типів зазвичай використовують порівняння:
typeof value === "string"Або:
typeof value === "number"TypeScript розуміє такі перевірки та змінює тип змінної всередині відповідної гілки.
stringРозглянемо функцію, яка приймає рядок або число:
function printLength(value: string | number): void {
if (typeof value === "string") {
console.log(value.length);
} else {
console.log(value);
}
}
printLength("TypeScript"); // 10
printLength(2024); // 2024Усередині if TypeScript знає, що value має тип string, тому доступна властивість length.
У гілці else залишається тип number, тому value можна використовувати як число.
Без перевірки TypeScript не дозволив би звернутися до length, оскільки числа такої властивості не мають.
numberПеревірка числа працює так само:
function double(value: string | number): string | number {
if (typeof value === "number") {
return value * 2;
}
return value.toUpperCase();
}
console.log(double(10)); // 20
console.log(double("hello")); // "HELLO"У гілці if значення має тип number, тому його можна множити.
Після if TypeScript знає, що значення має тип string, тому доступний метод toUpperCase().
Оператор typeof можна використовувати в кількох умовах:
function describe(value: string | number | boolean): string {
if (typeof value === "string") {
return `Рядок із довжиною ${value.length}`;
}
if (typeof value === "number") {
return `Число: ${value}`;
}
return value ? "Логічне значення true" : "Логічне значення false";
}
console.log(describe("cat"));
console.log(describe(42));
console.log(describe(true));Після першої перевірки TypeScript виключає string з можливих типів.
Після другої перевірки залишається лише boolean, тому в останній частині функції value має тип boolean.
Для примітивних значень найчастіше використовують такі перевірки:
function showType(value: string | number | boolean | undefined): void {
if (typeof value === "string") {
console.log("Рядок:", value);
} else if (typeof value === "number") {
console.log("Число:", value);
} else if (typeof value === "boolean") {
console.log("Логічне значення:", value);
} else {
console.log("Значення undefined");
}
}
showType("hello");
showType(100);
showType(false);
showType(undefined);Важливо порівнювати результат typeof саме з рядком:
"string"
"number"
"boolean"
"undefined"
"bigint"
"symbol"
"function"
"object"
У цій темі найчастіше потрібні "string", "number", "boolean" та "undefined".
unknownТип unknown означає, що значення може мати будь-який тип. На відміну від any, TypeScript не дозволяє використовувати таке значення без попередньої перевірки.
function printUnknown(value: unknown): void {
if (typeof value === "string") {
console.log(`Рядок у верхньому регістрі: ${value.toUpperCase()}`);
} else if (typeof value === "number") {
console.log(`Число з подвоєним значенням: ${value * 2}`);
} else if (typeof value === "boolean") {
console.log(`Логічне значення: ${value}`);
} else {
console.log("Непідтримуваний тип");
}
}
printUnknown("typescript");
printUnknown(21);
printUnknown(true);
printUnknown({ name: "Ada" });До перевірки TypeScript не знає, чи є value рядком, числом або іншим значенням. Після перевірки він дозволяє виконувати лише операції, які відповідають знайденому типу.
!==Для звуження типів можна використовувати не лише ===, а й !==.
function toText(value: string | number): string {
if (typeof value !== "number") {
return value.toUpperCase();
}
return value.toString();
}
console.log(toText("hello")); // "HELLO"
console.log(toText(42)); // "42"Якщо value не є числом, у цій гілці TypeScript знає, що це string.
nullУ JavaScript вираз:
typeof nullповертає:
"object"Це історична особливість JavaScript.
Тому перевірка typeof value === "object" сама по собі не відрізняє null від інших об'єктних значень:
function isObject(value: object | null): boolean {
return typeof value === "object" && value !== null;
}
console.log(isObject({})); // true
console.log(isObject(null)); // falseДля примітивних типів string, number, boolean і undefined така особливість не виникає.
Неправильно:
if (typeof value === string) {
// Помилка: string — це тип, а не значення JavaScript
}Правильно:
if (typeof value === "string") {
// Перевірка типу рядка
}typeofНеправильно:
if (typeof value === String) {
// Це не перевірка на рядок
}Правильно:
if (typeof value === "string") {
// Перевірка на рядок
}typeof розрізнить усі значенняtypeof зручно перевіряє примітивні типи, але не визначає конкретний різновид об'єкта. Наприклад:
console.log(typeof []); // "object"
console.log(typeof {}); // "object"
console.log(typeof null); // "object"Тому для звуження примітивних значень використовуйте конкретні перевірки "string", "number", "boolean" або "undefined".
Неправильно:
function uppercase(value: string | number): string {
return value.toUpperCase();
}TypeScript повідомить про помилку, оскільки value може бути числом.
Правильно:
function uppercase(value: string | number): string {
if (typeof value === "string") {
return value.toUpperCase();
}
return value.toString();
}typeof повертає рядок із назвою типу значення.
TypeScript використовує перевірки typeof для звуження типів.
Після перевірки typeof value === "string" значення розглядається як string.
Після перевірки typeof value === "number" значення розглядається як number.
Для логічних значень використовуйте "boolean", а для відсутнього значення — "undefined".
Результат typeof потрібно порівнювати з рядком.
typeof null повертає "object", тому null потребує окремої перевірки.