#наследование #typescript #множественное_наследование #mixins #прототипное_наследование
Есть класс и функция-конструктор. Делается попытка реализовать класс, являющийся
чем-то типа потомка обоих. Точнее, методы из прототипа функции-конструктора копируются
в прототип класса-потомка, унаследованный от класса.
Да, я понимаю, что это не полноценное наследование, но для решения задачи этого хватает.
Проблема в другом. Как заставить тайпскрипт воспринимать копируемые методы?
class First {
someMethod() {
console.log('someMethod from First');
}
}
function Second() {
console.log('Second');
}
Second.prototype.doSmth = function () {
console.log('doSmth from Second');
}
interface IBoth {
someMethod()
doSmth()
}
class Both extends First /* implements IBoth */ {
constructor() {
console.log('constructor of Both');
super();
Second.call(this);
}
}
for (let key in Second.prototype) {
Both.prototype[key] = Second.prototype[key];
}
На самом деле, надо обеспечить видимость методов ещё на уровень дальше
class Final extends Both {
doIt() {
this.someMethod();
//this.doSmth(); // Надо заставить видеть метод тут
(this as any as IBoth).doSmth(); // Компилируется, но это ужас
}
}
если при этом методы не будут видны из самого Both, то это годится.
Вот что я уже пробовал:
При попытке написать
class Both extends First implements IBoth {
возникает ошибка, что я не реализую методы интерфейса.
При переименовании Both в _Both и использовании
var Both = _Both as typeof _Both;
всё остаётся как было, что логично, поскольку тут никак не используется First.
При переименовании Both в _Both и использовании
var Both = _Both as typeof IBoth;
говорит, что не может найти имя IBoth.
Пробовал ещё несколько вариантов, но они совсем бредовые.
Что ещё можно сделать?
Попробовать можно тут: http://www.typescriptlang.org/Playground
Полный код для проверки
Запустить (код из правой панели) после добавления строки:
(new Final).doIt();
Вывод при запуске при раскомментированной строке this.doSmth();
constructor of Both
Second
someMethod from First
doSmth from Second
doSmth from Second
PS: Этот вопрос на английском.
Ответы
Ответ 1
Интерфейс вообще не нужен, нужно просто объявить прототипное поле с нужным типом: doSmth: () => void Она видима как свойство, а не как метод, но это непринципиально. Полный код: class First { someMethod() { console.log('someMethod from First'); } } function Second() { console.log('Second'); } Second.prototype.doSmth = function () { console.log('doSmth from Second'); } class Both extends First { constructor() { console.log('constructor of Both'); super(); Second.call(this); } doSmth: () => void } for (let key in Second.prototype) { Both.prototype[key] = Second.prototype[key]; } class Final extends Both { doIt() { this.someMethod(); this.doSmth(); //Both.prototype.doSmth(); // ok //Final.prototype.doSmth(); // ok } } PS: Надо было гуглить не всяческие варианты с наследованием, а typescript class prototype variable - сразу нашёл подходящий вариант.
Комментариев нет:
Отправить комментарий