Пошук уроків, статей та іншого контенту
Оголошуйте статичні члени класів і контролюйте читання та зміну властивостей через getters і setters.
Звичайні властивості та методи класу належать конкретним об’єктам. Статичні члени належать самому класу й існують в одному екземплярі незалежно від кількості створених об’єктів.
Для оголошення статичного члена використовують ключове слово static:
class User {
static readonly entityName = "User";
}Доступ до такого члена здійснюється через ім’я класу:
console.log(User.entityName);Статичний член не можна отримати через екземпляр класу:
const user = new User();
// Помилка TypeScript:
// console.log(user.entityName);До статичних членів належать:
статичні властивості;
статичні методи;
статичні getters;
статичні setters.
Статичну властивість зручно використовувати для даних, спільних для всіх екземплярів класу:
class Product {
static category = "electronics";
constructor(public name: string) {}
}
const phone = new Product("Phone");
const laptop = new Product("Laptop");
console.log(Product.category); // electronicsІ phone, і laptop використовують одну властивість Product.category, тому що вона належить класу, а не окремому об’єкту.
Статичний метод також викликається через клас:
class MathHelper {
static square(value: number): number {
return value * value;
}
}
console.log(MathHelper.square(5)); // 25Статичний метод не має доступу до властивостей конкретного екземпляра через this. У ньому this посилається на сам клас.
Звичайний метод може звертатися до нестатичних членів:
class Counter {
private value = 0;
increment(): void {
this.value += 1;
}
}А статичний метод не може безпосередньо звернутися до value, оскільки ця властивість існує лише в об’єктів Counter, а не в самому класі.
Getter — це спеціальний метод, який дає змогу читати значення як звичайну властивість:
class User {
private _name = "Anonymous";
get name(): string {
return this._name;
}
}
const user = new User();
console.log(user.name);Getter викликається без дужок:
user.name;А не як звичайний метод:
// Неправильно:
// user.name();Getter корисний, коли значення потрібно:
обчислити перед поверненням;
отримати з приватного поля;
приховати внутрішню реалізацію класу;
повертати значення в певному форматі.
Наприклад:
class Rectangle {
constructor(
private width: number,
private height: number,
) {}
get area(): number {
return this.width * this.height;
}
}
const rectangle = new Rectangle(10, 5);
console.log(rectangle.area); // 50area не зберігається окремо. Його значення обчислюється під час кожного читання.
Setter — це спеціальний метод, який виконується під час присвоєння значення властивості:
class User {
private _name = "Anonymous";
set name(value: string) {
this._name = value;
}
get name(): string {
return this._name;
}
}
const user = new User();
user.name = "Olena";
console.log(user.name); // OlenaЗовні setter використовується як звичайне присвоєння:
user.name = "Olena";Метод set name викликається автоматично.
Setter повинен приймати рівно один параметр і не може повертати значення:
class User {
private _name = "";
set name(value: string) {
this._name = value;
}
}Одна з основних переваг setter — централізована перевірка даних перед зміною властивості:
class User {
private _name = "";
get name(): string {
return this._name;
}
set name(value: string) {
const normalizedName = value.trim();
if (normalizedName.length < 2) {
throw new Error("Ім’я має містити щонайменше два символи");
}
this._name = normalizedName;
}
}
const user = new User();
user.name = " Olena ";
console.log(user.name); // OlenaSetter може нормалізувати значення, перевірити його та лише після цього записати у внутрішнє поле.
Для зберігання значення зазвичай використовують окреме приватне поле, наприклад _name. Це потрібно, щоб getter і setter не викликали самі себе рекурсивно.
Неправильний варіант:
class User {
get name(): string {
return this.name;
}
}this.name знову викликає getter name, який викликає себе без кінця.
Правильний варіант використовує окреме поле:
class User {
private _name = "";
get name(): string {
return this._name;
}
}Getters і setters також можуть бути статичними. У такому разі вони працюють із даними самого класу:
class Configuration {
private static _environment = "development";
static get environment(): string {
return Configuration._environment;
}
static set environment(value: string) {
const allowedValues = ["development", "production"];
if (!allowedValues.includes(value)) {
throw new Error("Непідтримуване середовище");
}
Configuration._environment = value;
}
}
console.log(Configuration.environment); // development
Configuration.environment = "production";
console.log(Configuration.environment); // productionСтатичний getter і setter викликаються через клас:
Configuration.environment;
Configuration.environment = "production";Не через екземпляр:
// Неправильно:
// const configuration = new Configuration();
// configuration.environment;У наступному прикладі:
role — статична властивість;
_count — приватна статична властивість;
count — статичний getter;
name — getter і setter екземпляра;
setter перевіряє та очищає ім’я перед збереженням.
class User {
static readonly role = "user";
private static _count = 0;
private _name = "";
constructor(name: string) {
this.name = name;
User._count += 1;
}
get name(): string {
return this._name;
}
set name(value: string) {
const normalizedName = value.trim();
if (normalizedName.length < 2) {
throw new Error("Ім’я має містити щонайменше два символи");
}
this._name = normalizedName;
}
static get count(): number {
return User._count;
}
}
const firstUser = new User(" Olena ");
const secondUser = new User("Andrii");
console.log(firstUser.name); // Olena
console.log(secondUser.name); // Andrii
console.log(User.role); // user
console.log(User.count); // 2
firstUser.name = " Kateryna ";
console.log(firstUser.name); // Kateryna
try {
secondUser.name = "A";
} catch (error) {
if (error instanceof Error) {
console.log(error.message);
}
}Результат виконання:
Olena
Andrii
user
2
Kateryna
Ім’я має містити щонайменше два символиЗверніть увагу на різницю:
firstUser.name; // getter екземпляра
firstUser.name = "Kateryna"; // setter екземпляра
User.count; // статичний getter
User.role; // статична властивістьGetter визначає тип значення, яке можна прочитати:
class Account {
private _balance = 0;
get balance(): number {
return this._balance;
}
}Setter визначає тип значення, яке можна присвоїти:
class Account {
private _balance = 0;
set balance(value: number) {
this._balance = value;
}
}Якщо getter і setter належать одній властивості, їхні типи мають бути сумісними. Значення, яке setter приймає, не повинно суперечити типу, який getter повертає.
class User {
get name(): string {
return "Olena";
}
}
const user = new User();
// Неправильно:
// user.name();Getter викликається без дужок:
console.log(user.name);class Config {
static version = "1.0";
}
const config = new Config();
// Неправильно:
// console.log(config.version);Правильний доступ:
console.log(Config.version);class User {
// Неправильно: getter викликає сам себе
// get name(): string {
// return this.name;
// }
}Використовуйте окреме внутрішнє поле:
class User {
private _name = "";
get name(): string {
return this._name;
}
set name(value: string) {
this._name = value;
}
}Setter змінює стан об’єкта, тому важливо не записувати некоректні дані:
class Product {
private _price = 0;
set price(value: number) {
if (value < 0) {
throw new Error("Ціна не може бути від’ємною");
}
this._price = value;
}
get price(): number {
return this._price;
}
}static створює член, який належить класу, а не його екземплярам.
Статичні члени викликаються через ім’я класу: ClassName.member.
Getter дає змогу читати значення як властивість, хоча всередині виконується метод.
Setter дає змогу контролювати присвоєння значення властивості.
Getter і setter використовують без дужок.
Для getter і setter зазвичай створюють приватне внутрішнє поле.
Статичні getters і setters працюють із даними класу та викликаються через клас.
Setter зручно використовувати для валідації й нормалізації даних.