Skip to content

Latest commit

 

History

History
103 lines (75 loc) · 3.58 KB

File metadata and controls

103 lines (75 loc) · 3.58 KB

Миксины (примеси)

TypeScript (и JavaScript) классы поддерживают строго одиночное наследование. К примеру, вы не можете сделать следующее:

class User extends Tagged, Timestamped { // ОШИБКА : невозможно множественное наследование
}

Еще один способ создания классов из повторно используемых компонентов - путем объединения более простых частичных классов, называемых миксины.

Идея проста: вместо класса A, расширяющего класс B для получения своей функциональности, функция B принимает класс A и возвращает новый класс с этой добавленной функциональностью. Функция B - это миксин.

[Миксин] - это функция, которая

  1. берет конструктор
  2. создает класс, расширяющий этот конструктор новыми функциями
  3. возвращает новый класс

Подробный пример:

// Требуется для всех миксинов
type Constructor<T = {}> = new (...args: any[]) => T;

////////////////////
// Примеры миксинов
////////////////////

// Миксин, который добавляет свойство
function Timestamped<TBase extends Constructor>(Base: TBase) {
  return class extends Base {
    timestamp = Date.now();
  };
}

// миксин, который добавляет свойство и методы
function Activatable<TBase extends Constructor>(Base: TBase) {
  return class extends Base {
    isActivated = false;

    activate() {
      this.isActivated = true;
    }

    deactivate() {
      this.isActivated = false;
    }
  };
}

////////////////////
// Использование для создания классов
////////////////////

// Простой класс
class User {
  name = '';
}

// Пользователь с отметкой времени
const TimestampedUser = Timestamped(User);

// Пользователь с отметкой времени и доступный для активации
const TimestampedActivatableUser = Timestamped(Activatable(User));

////////////////////
// Использование созданных классов
////////////////////

const timestampedUserExample = new TimestampedUser();
console.log(timestampedUserExample.timestamp);

const timestampedActivatableUserExample = new TimestampedActivatableUser();
console.log(timestampedActivatableUserExample.timestamp);
console.log(timestampedActivatableUserExample.isActivated);

Разложим этот пример на части.

Возьмите конструктор

Миксины берут класс и расширяют его новой функциональностью. Итак, нам нужно определить, что такое конструктор. Просто как:

// Требуется для всех миксинов
type Constructor<T = {}> = new (...args: any[]) => T;

Расширить класс и вернуть его

Довольно просто:

// Миксин, который добавляет свойство
function Timestamped<TBase extends Constructor>(Base: TBase) {
  return class extends Base {
    timestamp = Date.now();
  };
}

И это все 🌹