Типи даних TypeScript

TypeScript є строго типізованою мовою, і кожна змінна та константа в ній має певний тип. При цьому, на відміну від javascript, ми не можемо динамічно змінити раніше зазначений тип змінної.

У TypeScript є такі базові типи:

  • boolean: логічне значення true або false
  • number: числове значення
  • string: рядки
  • Array: масиви
  • кортежі
  • Enum: перерахування
  • Any: довільний тип
  • Symbol
  • null і undefined: відповідають значенням null і undefined у javascript
  • Never: також представляє відсутність значення і використовується як тип функцій, що повертається, які генерують або повертають помилку

Більшість із цих типів співвідносяться з примітивними типами з JavaScript.

Для встановлення типу застосовується знак двокрапки, після якого вказується назва типу. Приклади створення змінних:

let x: number = 10; 
let hello: string = "hello world";
let isValid: boolean = true;

Тобто в цьому випадку вираз let hello: string = "hello world" вказує, що змінна hello матиме тип string і значення hello world.

При цьому якщо в коді ми потім захочемо змінити тип, наприклад:

let hello: string = "hello world";
hello = 23;

То в процесі компіляції компілятор TypeScript видасть помилку.

Спочатку розглянемо примітивні типи даних, які є в TypeScript.

boolean

Тип Boolean представляє логічне значення true або false:

let isEnabled: boolean = true;
let isAlive: boolean = false;
 
console.log(isEnabled);
console.log(isAlive);

number

Тип number представляє числа, причому всі числа в TypeScript, як і в JavaScript, є числами з плаваючою крапкою. Тому за допомогою цього типу можна визначати як цілі числа, так і числа з плаваючою крапкою:

let age: number = 36;
let height: number = 1.68;

TS підтримує двійковий, вісімковий, десятковий і шістнадцятиричний записи чисел:

let decimal: number = 6;
// шістнадцятирична система
let hex: number = 0xf00d; // 61453 у десятковій
// двійкова система
let binary: number = 0b1010; // 10 у десятковій
// восьмирична система
let octal: number = 0o744; // 484 у десятковій
console.log(decimal);
console.log(hex);
console.log(binary);
console.log(octal);

string

String представляє рядки. Як і в JavaScript, у TypeScript рядки можна укладати в подвійні або в одинарні лапки:

let firstName: string = "Tom";
let lastName = 'Johns';

Крім того, TypeScript підтримує таку функціональність, як шаблони рядків, тобто ми можемо задати шаблон у косих лапках (`), так, наче ми пишемо звичайний рядок, і потім у сам рядок можна вбудовувати різні вирази за допомогою синтаксису ${ expr }, де expr - це вираз. Наприклад:

let firstName: string = "Tom";
let age: number = 28;
let info: string = `Ім'я ${firstName} Вік: ${age}`;
console.log(info); // Ім'я Tom Вік: 28

Косі лапки також можна застосовувати для встановлення багаторядкового тексту:

let sentence: string = `Hello World!
Goob bye World!`;

bigint

Для представлення дуже великих чисел у TypeScript додано спеціальний тип bigint. Цей тип дає змогу зберігати числа більші, ніж 253 - 1 - більше, ніж дозволяє тип number.

Є два способи визначення об'єкта цього типу. Перший спосіб - за допомогою функції BigInt():

const num1: bigint = BigInt(100);
console.log(num1);

Другий спосіб - за допомогою додавання символу n після числового значення:

const num2: bigint = 100n;
console.log(num2);

Слід зазначити, що цей тип - частина стандарту ES2020, тому під час компіляції слід встановити цей стандарт як цільовий через параметр target. Наприклад, у файлі tsconfig.json:

{
    "compilerOptions": {
        "target": "es2020",
        "outFile": "app.js"
    }
}

Виведення типу

Але можна в принципі і не вказувати тип змінної. Наприклад:

let hello = "hello world";
hello = 23;

У цьому разі TypeScript автоматично виведе тип із присвоюваного цій змінній значення. Так, у першому рядку компілятор TS побачить, що змінній hello присвоюється рядок, тому для неї буде використовуватися тип string. Однак у другому рядку знову ж таки компілятор видасть помилку, оскільки hello змінній уже визначено тип string. А нове значення передбачає тип number.

Тип any

Any описує дані, тип яких може бути невідомим на момент написання програми.

let someVar: any = "hello";
console.log(someVar); // зараз someVar - це рядок
someVar = 20; 
console.log(someVar); // зараз someVar - це number

Оскільки тут застосовується тип any, то цей код скомпілюється без помилок, незважаючи на зміну рядкового значення на числове. І також ми можемо оголошувати масиви цього типу:

var someArray: any[] = [ 24, "Tom", false];

Якщо змінна визначається без значення і вказівки типу, і тільки згодом під час роботи програми їй присвоюється значення, тоді вважається, що вона має тип any:

let x; // тип any
x = 10; 
x = "hello";    

З одного боку, any може здатися зручним типом. Однак, з іншого боку, він позбавляє програму переваг мови TypeScript, зокрема, статичної типізації. Відповідно може привнести в програму потенційні помилки, пов'язані з типізацією даних, які компілятор не зможе відстежити на етапі компіляції.

Перевірка типу
За допомогою оператора typeof ми можемо перевірити тип змінної. Це може бути необхідно, коли ми хочемо виконати деякі операції зі змінною, але нам невідомий її точний тип (наприклад, змінна представляє тип any). Ця функціональність ще називається type guards або захист типу:

let sum: any;
sum = 1200;
sum = "тисяча двісті";
let result: number = sum / 12;
console.log(result); // NaN - рядок не можна розділити на число

Змінна sum може зберігати будь-яке значення, однак ділення може працювати тільки з числами. Тому перед діленням виконаємо перевірку на тип:

let sum: any;
sum = 1200;
 
if (typeof sum === "number") {
     
    let result: number = sum / 12;
    console.log(result);
}
else{
    console.log("invalid operation");
}

Оператор typeof повертає тип значення. Наприклад, вираз typeof sum у даному випадку повертає "number", оскільки змінна sum представляє число.

Оператор typeof може повертати такі значення:

  • "string"
  • "number"
  • "bigint"
  • "boolean"
  • "символ"
  • "невизначений"
  • "об'єкт"
  • "функція"