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

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

У цій статті я більше фокусуюсь на тому щоб затронути світ TypeSript та показати вам його особливості без занурення в деталі і окремі аспекти. Якщо вам цікаво дізнатись про якийсь конкретний аспект більше підписуйтесь на мій блог, або пишіть в комментарі про що саме ви б хотіли почитати.

Давайте починати!

Що таке Typescript?

TypeScript був розроблений Microsoft і вперше випущений у 2012 році.

TypeScript — це мова програмування, розроблена Microsoft у 2012 році як надбудова JavaScript. Це означає, що будь-який код JavaScript є валідним TypeScript кодом. Натомість TypeScript привносить деякі нові функції та синтаксис до JavaScript, що робить код більш надійними, зручним в обслуговуванні та масштабуванні.

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

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

І останне що хотілось би зазначити, TypeScript підтримує об’єктно-орієнтовані принципи, такі як класи (classes), інтерфейси (interfaces), перерахування (enumerations) та узагальнена типізація (generic types) які у повній мірі розкривають потенціал та силу цієї мови програмування.

А тепер прийшов час коротко зануритись в найголовніші на мій погляд особливості Typescript.

Строга типізація

Перша і, мабуть, найкрутіша особливість TypeScript — це строга типізація (англ. static typing). Строга типізація це концепт мови програмування, в якому від розробника потребується явно вказувати тип данних змінних, аргументів та інших конструкцій у коді.

Це у свою чергу дозволяє компілятору “знати” тип змінної або виразу ще до моменту фактичного запуску програми і дозволить виявити помилки повʼязанні з неспівпадінням типів даних раніше.

Щоб було зрозуміліше, дозвольте показати вам простий приклад:

let myString: string;

myString = 'hello';

Тут ми визначаємо змінну myString, а після двокрапки вказуємо тип змінної - string. Це і є строга типізація в TypeScript, де змінній присвоюється тип данних у коді, а не в момент виконання програми як у JavaScript.

Далі у прикладі ми присвоюємо рядкове значення ‘hello’ змінній myString. Під час компіляції данний рядок не спричинить появу помилки оскільки ми вказали тип змінної у визначенні.

Однак, якщо ми присвоїмо числове значення даній змінній, як вказано у третьому рядку, то це викличе помилку типу під час компіляції, оскільки TypeScript виявить невідповідність типу данних.

myString = 42; // Помилка під час компіляції

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

Інтерфейси

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

Для більшого розуміння пропоную одразу розглянути приклад:

interface Person { 
  name: string; 
  age: number; 
}

У наведеному прикладі ми визначаємо простий інтерфейс, що описує обʼєкт Person, з трьома атрибутами: name, age.

function sayHello(person: Person) { 
  console.log("Hello, " + person.name + "!");
}

Ми також створюємо функцію під назвою sayHello, яка приймає один аргумент person. Як ви можете помітити, ми вказуємо аргументу person тип Person, тобто використовуємо створений нами інтерфейс як тип аргументу. Це дозволяє нам у тілі функції посилатися на атрибут name аргументу person при виводі привітання в консоль. Тип аргументу у вигляді інтерфейсу також вкаже компілятору що переданий аргумент має задовільняти наш інтерфейс, що у разі невиконання видасть помилку на єтапі компіляції.

Тобто якщо створити об’єкт під назвою john типу Person, як показано у наступному шматочці коду, і зазначити йому дві обов'язкові властивості name та age, ми можемо викликати функцію sayHello, передавши їй об’єкт john як аргумент, то функція виведе “Hello, John!” в консоль.

const john: Person = { 
  name: "John",
  age: 30
};

sayHello(john); // Результат: Hello, John!

Однак якщо ми викличемо функцію sayHello з аргументом рядкового типу “Bob”, то компілятор видасть помилку, вказавши що передане значення не задовільняє вказаний тип Person.

sayHello("Bob"); // Помилка під час компіляції

Класи

Наступна чудова особливість TypeScript — це класи (англ. class). Класи дозволяють визначати об’єкти зі спільними властивостями, подібно до інтерфейсів. Але на відміну від інтерфейсів, класи дозволяють також визначати загальні методи екземплярів класу.

Щоб зрозуміти, давайте розглянемо приклад:

class Rectangle { 
  width: number; 
  height: number;
  
  constructor(width: number, height: number) { 
    this.width = width;
    this.height = height;
  }

  getArea(): number {
    return this.width * this.height;
  } 
}

Тут ми визначаємо клас Rectangle (прямокутник) із двома властивостями width та height, які, як ви могли здогадатись, відповідають довжині та ширині прямокутника.

Ми також визначаємо метод-конструктор (constructor), який приймає два аргументи та призначає їх властивостям width та height. По суті, constructor є ексклюзивним методом класів, дозволяючи вам визначати, який код буде виконано під час ініціалізації єкземпляру класу. 

Також ми визначимо ще один метод під назвою getArea, який обчислює та повертає площу прямокутника.

const rect = new Rectangle(10, 20); 
console.log(rect.getArea()); // Результат: 200

Тепер створимо екземпляр класу Rectangle під назвою rect із шириною 10 і висотою 20. А оскільки об’єкт rect є єкземпляром класу Rectangle, ми можемо викликати його метод getArea для обчислення та виведення його площі в консолі.

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

Перерахування

Перерахування (англ. еnumeration або enum) дозволяють визначити набір іменованих констант повязаних між собою однією абстракцією. 

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

enum Direction { 
  Up,
  Down,
  Left,
  Right,
}

console.log(Direction.Up); // 0 
console.log(Direction.Down); // 1 
console.log(Direction.Left); // 2 
console.log(Direction.Right); // 3

У прикладі вище ми визначаємо enum під назвою Direction, яка містить чотири значення, що відповідають чотирьом векторам напрямку: up, down, left і right. Тепер ви можете звертатись до цих значень, використовуючи ім’я enumeration, після якого стоїть крапка та одне з імен значень, які ви вибрали. Під час виведення кожного зі значень з переліку ми можемо побачити, що вони відповідають числам від 0 до 3. Цей тип enum називається числовим, оскільки TypeScript неявно присвоїв кожному значенню число.

Ви також можете самостійно вказати числа так:

enum Direction { 
  Up = 2,
  Down = 4,
  Left = 6,
  Right = 8,
}

console.log(Direction.Up); // 2 
console.log(Direction.Down); // 4 
console.log(Direction.Left); // 6 
console.log(Direction.Right); // 8

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

Існує також інший тип enumeration - це рядкові перерахування. У цьому випадку ми присвоюємо рядок кожному значенню. Це може бути корисним, якщо ви хочете використовувати або повертати значення перерахування.

enum Direction { 
  Up = "Up",
  Down = "Down",
  Left = "Left",
  Right = "Right",
}

console.log(Direction.Up); // Up
console.log(Direction.Down); // Down 
console.log(Direction.Left); // Left 
console.log(Direction.Right); // Right

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

Узагальнена типізація

Наступна особливість, яку я хочу вам показати, є трохи складнішою за інші, але я спробую пояснити її вам простим способом, оскільки вона підкреслює всю красу та універсальність TypeScript. Ця функція - Узагальнена типізація (англ. generic types).

Узагальнені типи TypeScript дозволяють створювати тип або функцію, які можуть працювати з різними типами даних, без зазначення точного типу заздалегідь.

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

Наприклад, ми хочемо створити функцію під назвою identity, яка для простоти поверне нам аргумент, який ми їй передали. Але також ми хочемо, щоб ця функція працювала для будь-якого типу аргументу. Такі функції можна записати, як показано вище, де ми передаємо загальний тип T для представлення типу аргументу та типу значення, що повертається.

let output = identity<string>("hello");
console.log(output); // Output: "hello"

output = identity<number>(42); 
console.log(output); // Output: 42

Це дозволяє нам викликати функцію identity з рядковим аргументом, просто передаючи тип string в дужки зі стрілками або за допомогою числового аргументу, передаючи тип number.

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

Підсумки

Коротко підсумовуючи, я хотів би перерахувати плюси використання TypeScript.

Першою і, мабуть, найбільшою перевагою Typescript є безпечність типів (англ. type safety), яка досягається за допомогою статичної типізації, інтерфейсів, перерахувань, тощо та допомагає вам запобігати помилкам, чітко визначаючи типи для змінних, функцій і об’єктів.

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

Загалом, використовуючи функціонал TypeScript, ви можете досягти більшої читабельності, зручності підтримки та масштабування свого коду.

Крім того, TypeScript забезпечує кращі інструменти та підтримку IDE із такими функціями, як навігація кодом і автодоповнення.

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

Поділись своїми ідеями в новій публікації.
Ми чекаємо саме на твій довгочит!
Дмитро Ткачук
Дмитро Ткачук@dmytro_tk

344Прочитань
3Автори
4Читачі
На Друкарні з 20 травня

Вам також сподобається

Коментарі (3)

JavaScript це JavaScript на стероїдах

Вам також сподобається