Есть класс и функция-конструктор. Делается попытка реализовать класс, являющийся чем-то типа потомка обоих. Точнее, методы из прототипа функции-конструктора копируются в прототип класса-потомка, унаследованный от класса.
Да, я понимаю, что это не полноценное наследование, но для решения задачи этого хватает.
Проблема в другом. Как заставить тайпскрипт воспринимать копируемые методы?
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: Этот вопрос на английском.
Ответ
Интерфейс вообще не нужен, нужно просто объявить прототипное поле с нужным типом:
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 - сразу нашёл подходящий вариант.
Комментариев нет:
Отправить комментарий