Щоб оголосити абстрактний клас, перед ним потрібно вказати ключове слово 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 є те, що багато сучасних середовищ розробки підтримують його, і показують попередження відразу в процесі написання коду.