Відповіді на запитання по Typescript

Тут ти знайдеш відповіді на питання, які часто зустрічаються на співбесідах

Щоб оголосити абстрактний клас, перед ним потрібно вказати ключове слово Abstract. Абстрактні класи схожі на звичайні класи, але ми не можемо створювати сутності цих класів. Абстрактні класи служать для опису загальних параметрів та методів для класів спадкоємців.

abstract class Figure { getArea(): void{ console.log("Not Implemented") } } class Rectangle extends Figure{ constructor(public width: number, public height: number){ super(); } getArea(): void{ let square = this.width * this.height; console.log("area = ", square); } } let rectangle: Figure = new Rectangle(20, 30) rectangle.getArea(); // area = 600

void - вказує на те, що у методу або функції відсутнє значення що повертається або вона повертає undefined
never - вказує на те, що функція ніколи нічого не повертає (викидає виняток або виконується нескінченно)

function f(a: number): void { let b = a * a; } function e(): never { throw new Error(); }

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

function identity<T>(arg: T): T { return arg; } let output1 = identity<string>("Hello World!"); let output2 = identity<number>(255); console.log(output1) console.log(output2)

interface і type в цілому схожі. Але є й відмінності:

  • type може визначати примітивні типи, інтерфейси що неспроможні.

    //✅
    type SomeString = string;
    const str: SomeString = '';
    
    //❌
    interface SomeStringByInterface = string;
    //TS2693: 'string' only refers to a type, but is being used 
    //as a value here.
    
  • Об'єднання типів можна зробити тільки використовуючи type

    type Fruit = 'apple' | 'lemon';
    type Vegetable = 'potato' | 'tomato';
    type Food = Fruit | Vegetable;
    
    const apple: Food = 'apple';
    
  • Інтерфейси підтримують злиття імен, type - ні.

    //✅
    interface User {
      fullName: string;
    };
    
    interface User {
      email: string;
    };
    
    const user: User = {
      fullName: "Philip Nedelev",
      email: "some@email.com"
    };
    
    //❌
    type SomeValue = string;
    type SomeValue = number;
    //TS2300: Duplicate identifier 'SomeValue'.
    
  • Інтерфеси використовують ключове слово extends для успадкування, а типи використовують символ & для реалізації перерахування.
    Також є деякі особливості при наслідуванні, їх ви можете побачити на прикладі нижче

    //✅
    type Parent = {
      printName: (name: number) => void;
    };
    type Child = Parent & {
      printName: (name: string) => void;
    };
    const Person: Child = {
      printName: (name: number | string) => {
        console.log(name);
      }
    };
    
    
    //❌
    interface Parent {
      printName: (name: number) => void;
    }
    interface Child extends Parent {
      printName: (name: string) => void;
    }
    //TS2430: Interface 'Child' incorrectly extends interface 'Parent'.
    //when an interface is inherited, the type cannot conflict with 
    //the super type, it can only be extended
    
  • Типи об'єктів, що зіставляються, реалізуються тільки за допомогою type

    type MyPartial<T> = {
      [P in keyof T]?: T[P]
    }
    
  • Працюючи з type ви можете надавати типи використовуючи ключове слово typeof

    const carrot = { name: 'carrot', weight: 1 };
    
    type Vegetable = typeof carrot;
    
    const tomato: Vegetable = {
      name: 'tomato',
      weight: 2,
    };
    

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

TypeScript підтримує 6 елементів ООП:

  • модулі - це окремі закінчені фрагменти програми з інкапсульованою логікою
  • класи - це шаблони для створення об'єктів
  • інтерфеси - це перелік властивостей та методів, які повинні бути визначені та реалізовані в класі успадкованому від інтерфейсу
  • успадкування - це концепція згідно з якою клас може успадковувати та використовувати дані та методи іншого класу
  • типи даних - безліч значень об'єднаних загальними характеристиками та набором операцій
  • методи - функції всередині класу які описують якусь логіку

Якщо до властивостей та методів класів не застосовується модифікатор доступу, то такі властивості та функції будуть public по дефолту.

public - визначає поля і методи, які доступні як у класах, в яких вони оголошені, так і в класах нащадках. Також до публічних полів можна звертатися через екземпляри класу.

protected - визначає поля і методи, які з поза класу видно тільки в класах-спадкоємцях

private - визначає поля та методи, які доступні лише контексту класу в якому вони визначені

// publick example class Animal { public nickname: string; constructor(){ this.nickname = 'animal'; } } class Bird extends Animal { constructor(){ super(); super.nickname = 'bird'; } } let animal: Animal = new Animal(); animal.nickname = 'newanimal'; let bird: Bird = new Bird(); bird.nickname = 'newbird'; __________________________________ //protected example class Animal { protected isUpdate: boolean; constructor(){ this.isUpdate = false; } } class Bird extends Animal { constructor(){ super(); super.isUpdate = false; } } let animal: Animal = new Animal(); animal.isUpdate = true; // Error let bird: Bird = new Bird(); bird.isUpdate = true; // Error __________________________________ //private example class Animal { private metainfo: string; constructor(){ this.metainfo = '...'; } } class Bird extends Animal { constructor(){ super(); super.metainfo = 'bird'; // Error } } let animal: Animal = new Animal(); animal.metainfo = 'newanimal'; // Error let bird: Bird = new Bird(); bird.metainfo = 'newbird'; // Error

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

enum Color { Red = "#c10000", Blue = "#007ac1", Pink = 0xc10050, White = 255 } let a = Color.Red // Color let b = Color.Green // Error TS2339: Property 'Green' does not exist on type 'typeof Color'

JavaScript компілюється і виконується середовищем виконання званим двигуном. Найпоширенішими двигунами є V8 (NodeJS, Chrome, Opera), SpiderMonkey (Firefox), JSCore (Safari) і Chakra (Edge).

Якщо у вашому JS коді є якась помилка, ви дізнаєтеся про це лише в процесі виконання програми. Це часто призводить до помилок типу ReferenceError: something is not defined
або TypeError: object.something is not a function .

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

Далі скомпельований JS код обробляється JS движком залежно від платформи де ви його виконуєте.

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

Інші питання

Якщо у тебе є питання чи пропозиції, напиши мені: Telegram | LinkedIn
© 2023 All rights reserved