Почему это работает в JavaScript, но TypeScript считает его недействительным? - PullRequest
0 голосов
/ 13 апреля 2020

Я попытался создать базовый класс, который имеет служебный метод stati c для создания класса, который использует return new this(). Но это не работает, когда у меня есть расширение подкласса, потому что этот служебный метод возвращает базовый класс вместо подкласса, который отличается от JavaScript.

Минимальный пример:

class Base {
    static create() {
        return new this()
    }
}
class Sub extends Base {
    fn() {
        return this
    }
}
Sub.create().fn() // TypeScript error, JavaScript ok
Base.create().fn() // TypeScript error, JavaScript error

Игровая площадка TypeScript

1 Ответ

3 голосов
/ 13 апреля 2020

Это потому, что TypeScript не имеет polymorphi c this типов для методов stati c. Существует давняя открытая проблема, microsoft / TypeScript # 5863 , с просьбой предоставить такую ​​функцию. Пока это не часть языка, но, к счастью, комментарии по этому вопросу описывают обходной путь, который должен помочь вам найти то поведение, которое вам нужно:

class Base {
    static create<T extends Base>(this: new () => T) {
        return new this()
    }
}

Здесь мы делаем create() a generi c метод с параметром типа T extends Base, который может быть вызван только для объекта, чей контекст this является конструктором с нулевым аргументом и возвращает значение типа T.

Поэтому компилятор знает, что Sub.create() вернет Sub, а Base.create() вернет Base:

Sub.create().fn() // okay
Base.create().fn() // Property 'fn' does not exist on type 'Base'

Это также имеет преимущество перед существующим кодом в том, что следующее теперь является ошибкой:

class Oops extends Base {
    x: string;
    constructor(x: string) {
        super();
        this.x = x.toUpperCase();
    }
}

Oops.create(); // error!

Класс Oops не имеет конструктора с нулевым аргументом, и поэтому реализация Oops.create() в итоге вызовет new Oops() без требуемого параметр и вызвать ошибку времени выполнения при попытке вызвать toUpperCase() на undefined.


Хорошо, надеюсь, это поможет; удачи!

Детская площадка ссылка на код

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...