Важной причиной для выбора Typescript в качестве нашего языка проектирования было предотвращение ошибок времени выполнения, таких как «X не определен». Однако мы все еще сталкиваемся с некоторыми из них при вызове виртуального метода из конструктора суперкласса.
Разве компилятор не должен выдавать ошибку за это?
В документации Typescript не упоминается, что вызовы виртуальных методов недопустимы (точнее: может не использоваться this
).
Только один из участников предлагает написать правило проверки для проверки этого, другой пометил его как Ограничение проектирования
abstract class Base {
constructor(protected readonly numbers: number[]) {
this.initialise()
}
protected abstract initialise(): void
}
class Extended extends Base {
private readonly squares: number[] = []
protected initialise() {
this.numbers.forEach( num => this.squares.push( num * num ) )
}
}
const extended = new Extended( [1,2,3,4,5] )
Приведенный выше код вызывает ошибку во время выполнения (проверьте ее на Playground . Вы увидите, что он будет проходить красиво, без ошибок или даже предупреждений. Но когда вы запустите его, консоль покажет ошибку )
Uncaught TypeError: Cannot read property 'push' of undefined
at <anonymous>:30:68
at Array.forEach (<anonymous>)
at Extended.initialise (<anonymous>:30:22)
at Extended.Base (<anonymous>:17:14)
at new Extended (<anonymous>:24:47)
Свойство squares
для Extended все еще не определено, когда конструктор Base вызывает метод initialise. Это связано с тем, как код преобразуется в Javascript.
Хотя я могу понять основную причину, это очень раздражает компилятор не жалуется на это. Я видел предложения сделать «ленивую» инициализацию членов вроде Extended.squares
, но мне очень нравится сохранять членов readonly
в максимально возможной степени.
На самом деле, я действительно ожидал бы, что приведенный ниже код будет функционировать правильно (имея массивы numbers
и squares
, заполненные пятью числами). Но до тех пор, пока не разрешено использовать this
до завершения всех суперконструкторов, компилятор должен указывать это.