Теорія типів

Теорія типів

  • 8 липня
  • читати 15 хв
Володимир Шайтан
Володимир Шайтан Technical Lead у Zoot, Викладач Комп'ютерної школи Hillel.

Усі ми колись з чогось починали, хтось починає зараз. Для нас усіх на початку є одна незрозуміла штука, яку б мову програмування ми не вчили — типи даних. Про них сьогодні й поговоримо.

Популярність TypeScript зростає, а з нею і актуальність через сувору типізацію TypeScript. Завдяки своєму досвіду, я з теорією типів на “ти”. Тому хочу допомогти зрозуміти і вам. Поїхали.

Більшість людей, які відкрили цю статтю, вірогідно, вже знайомі з JavaScript і знають, що TypeScript — так звана надмножина JavaScript, яка виправляє багато моментів оригінальної мови. Це означає, що ви можете без глобальних проблем перейти з однієї мови на іншу, не переписуючи код тотально.

І тут ми підійшли до запитання: а як саме ми пишемо код на JavaScript? Усе просто. Ми, не замислюючись, пишемо код за типами, ми мислимо типами. Пояснюю: це буде список з числами чи індексами, або список продуктів тому я назву його щось типу array/indexList і т. д., або це буде змінна, де буде лежати речення зі звертанням, яке буде генеруватися залежно від того, що введе користувач.

Це дає нам розуміння про те, як далі з цим працювати, які методи використовувати для вирішення тих чи інших задач, що можна застосовувати, а що — немає сенсу.

Вам може здатися, що ви готові до строгої типізації, якщо ви просто видасте своїм змінним якісь типи. Але не все так просто. Загалом, TypeScript має всі типи даних, які має JavaScript, і ще трошки. Ці типи — усім відомі примітивні number, string, boolean, null, undefined, symbol, і bigint. А також:

  • масиви;
  • tuples, які називають “кортежі” — масиви, які мають фіксовану кількість елементів;
  • enums (переліки або обчислення) — не доповнення до JavaScript, а саме можливість TypeScript. Цей тип надає можливість розробнику визначити перелік або набір іменованих констант. Має такий вигляд:
enum Direction {
 Up = 1,
 Down,
 Left,
 Right,
}
  • any — тип даних, який потрібно використовувати тоді, коли тип даних змінної невідомий на момент написання коду, а стане відомий при компіляції;
  • unknown — тип, схожий на any, але більш безпечний.

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

let value: unknown; 
value = 42;
value = "hello";
value = true;

Обмеження мають такий вигляд:

let value: unknown = "hello";
console.log(value.length); // Помилка: об'єкт типу 'unknown' не має властивості 'length'
  • void — використовується для функцій, що нічого не повертають;
  • never — тип, який використовується для функцій, які повертають помилки або зациклюються.

Також існують комплексні типи даних:

  • object;
  • interfaces — використовуються для визначення структури обʼєктів. Інтерфейс визначає форму об'єкта, включаючи імена властивостей і типи їх значень.

Важливо зазначити, що інтерфейси не мають реалізації, вони лише описують структуру.

Union types або об’єднані типи:

let value: number | string;
value = 42;    // Валідно
value = "Hello";  // Валідно

Intersection types або перетинання типів:

interface A {
  propA: string;
}
interface B {
  propB: number;
}
let ab: A & B = { propA: "Hello", propB: 42 };

І ми перейшли до дженериків.

Дженерики (Generics) дозволяють створювати компоненти, які можуть працювати з різними типами даних, зберігаючи при цьому інформацію про ті самі типи. Найчастіше використовуються для створення повторно використовуваних компонентів, таких як функції, класи, інтерфейси або типи, які можуть працювати з різними типами даних без втрати типобезпеки.

Якщо ми говоримо про дженерик-функцію, то матиме приблизно такий вигляд:

function identity<T>(arg: T): T {
  return arg;
}

let output1 = identity<string>("Hello"); // output1 має тип string
let output2 = identity<number>(42);      // output2 має тип number

Дженерик-інтерфейси мають такий вигляд:

interface Pair<T, U> {
  first: T;
  second: U;
}

let pair: Pair<string, number> = {
  first: "hello",
  second: 42
};

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

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

  • typeof;
  • instanceof.

На них ми зупинятися не будемо, а перейдемо далі, до операторів типів, які мають пряме відношення виключно до TypeScript: typeof в контексті типів (неочікувано, правда?)

Це означає, що TypeScript дає змогу розширити звичні нам можливості typeof таким чином:

let s = "hello";
let n: typeof s; // тип 'n' тепер є 'string'

Виглядає просто, на практиці зручно.

keyof — повертає об’єднання ключів об’єкту. Звучить складно, пояснюю:

interface Person {
  name: string;
  age: number;
}
type PersonKeys = keyof Person; // 'name' | 'age'

in в контексті умовних типів:

type Keys = 'a' | 'b' | 'c';
type Obj = { [K in Keys]: string };

Типи даних — ключ до розуміння будь-якої мови програмування, і їх вивчення відкриває нові горизонти для вашого коду. TypeScript зі своєю суворою типізацією може спочатку здатися складним, але насправді він робить ваше життя простішим та приємнішим. Він надає вам інструменти для створення чистого, безпечного і передбачуваного коду.

Починаючи свій шлях у TypeScript, ви помітите, як він допомагає уникати багатьох помилок, які трапляються в JavaScript. Ви почнете писати код, який буде легше читати, тестувати й  підтримувати. Досліджуйте примітивні типи, заглиблюйтесь у дженерики, експериментуйте з інтерфейсами та операторами типів — усе це зробить вас більш досвідченим і впевненим розробником.

Пам’ятайте, що сувора типізація — це ваш союзник у створенні якісного коду. Продовжуйте вивчати, ставити запитання, експериментувати та не зупиняйтесь на досягнутому. TypeScript не тільки допоможе вам писати код краще, але й відкриє нові можливості для професійного зростання, бо зараз усі хочуть універсальних, готових занурюватись у питання, розробників. 

Вміти розібратись у чомусь — найголовніша, найдорожча навичка абсолютно для всіх і завжди. Саме це продасть вас, як працівника, саме це буде вашим рекомендаційним листом для наступного роботодавця. Розвивайте, тренуйте це і все у вас вийде.

Ми незабаром зустрінемося з вами за обговоренням нових цікавих тем і речей. До зустрічі!

Рекомендуємо курси по темі