В TypeScript мы не можем наследовать или расширять несколько классов, но Mixins помогает нам обойти это ограничение.
Миксины создают частичные классы, которые мы можем объединить в единый класс, содержащий все методы и свойства из частичных классов.
Для примера, давайте преставим что у нас есть два класса Car и Lorry у которых есть методы drive и carry и мы хотим создать третий класс Truck. Класс Truck должен содержать оба метода drive и carry, но в Typescript мы можем наследовать только от одного класса, для решения это проблемы мы можем испльзовать Mixins:
Чтобы создать миксин, мы воспользуемся двумя функциями TypeScript:
- Interface class extension
- Declaration merging
Interface class extension
В отличие от классов, интерфейсы могут расширять несколько классов в TypeScript. Когда интерфейс расширяет класс, он расширяет только члены класса, но не их реализацию, потому что интерфейсы не содержат реализаций.
Declaration merging
Когда две или более сущности объявленны с одним и тем же именем Typescript объеденяет их в одну:
Примечание: объеденение свойств идет по принципу merge down, т.е если у нас есть два интерфейса с одним и тем же свойством в результирующий интерфейс попадет то свойство которое было объявленно последним.
Используя эти две функции в TypeScript, мы можем создать интерфейс с тем же именем, что и Truck, и расширить классы Car и Lorry:
из-за объеденения описаний ( Declaration merging ) класс Truck и интерфес Truck были объеденены. Это значит что класс Truck будет содержать определения методов которые были объявлены в классах Car и Lorry. Запомните только объявления а не их реализацию, еще раз интерфейсы опизсывают только опеределения без конкретной реализации. Для того что бы класс Truck по мимо объявления имел доступ к реализации нам нужно воспользоватся функцией хелпером приер которой описан в официальной документации:
Функция принимает имя класса, в который мы хотим скопировать реализации, в качестве первого аргумента, который в нашем случае является Truck, и принимает массив классов, из которых мы хотим скопировать реализации, как второй аргумент, который в нашем дело это Car и Lorry.
Теперь мы можем получить доступ к методам классов Car и Lorry в объекте Truck