Прототип класса TypeScript включает член экземпляра - PullRequest
1 голос
/ 20 марта 2019

Ниже приведен мой фрагмент кода:

class Hello {
    abc = {
        a: 'l',
        b: 1,
    }
    k = (prop: keyof typeof Hello.prototype.abc) => {
        console.log(prop)
    }
}

И код отлично работает на официальной площадке TypeScript.

Поэтому мой вопрос: abc является экземпляром класса Hello, Почему я могу получить доступ к свойству abc из Hello.prototype?

Ответы [ 2 ]

3 голосов
/ 20 марта 2019

Проблема в том, что для class X {...} тип X.prototype представлен в TypeScript как X, тип экземпляра класса.Из (устаревшего, но все еще значимого для этого вопроса) Спецификация языка TypeScript :

Тип функции конструктора, введенной объявлением класса, называется типом функции конструктора.Тип функции конструктора имеет следующие члены:

... [snip] ...

  • Свойство с именем 'prototype', тип которого является экземпляром классатип с типом Любой, предоставленный в качестве аргумента типа для каждого параметра типа.

Таким образом, TypeScript считает, что тип Hello.prototype равен Hello.Это, конечно, не так в целом.Это верно для методов, но не для свойств экземпляра, как вы обнаружили.

Я искал проблемы в Github , но не нашел ничего, упоминающего об этом.Возможно, стоит открыть новый выпуск, предлагающий расширить тип прототипа класса, включив в него только методы.

РЕДАКТИРОВАТЬ: Эх, думаю, существует несколько существующих выпускает по этому поводу, которые по сути были отклоненными предложениями, потому что это повредило бы больше, чем помогло бы.

Я точно знаю, что это может испортить некоторые вещи (в настоящее время проверка x instanceof Class будетсузить тип x до Class['prototype'], который, если его расширять, чтобы он включал только методы, повсеместно нарушал бы код каждого), поэтому я сомневаюсь, что они примут такое предложение. Но было бы неплохо, чтобы было официальное слово в этом вопросе.

В любом случае, резервное копирование вашей проблемы ... Код времени выполнения хорош, верно?И вы хотите, чтобы это работало:

new Hello().k("a");

и вы хотели бы, чтобы компилятор предупреждал о

new Hello().k("oopsie"); // error

?Если это так, то я бы предложил полностью исключить prototype из уравнения и вместо этого использовать тип поиска вместо типа экземпляра Hello:

class Hello {
    abc = {
        a: 'l',
        b: 1,
    }
    k = (prop: keyof Hello['abc']) => {
        console.log(prop)
    }
}

Теперь это ведет себяпо желанию и не демонстрирует странности вокруг свойств экземпляров и прототипов классов в TypeScript.

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

0 голосов
/ 20 марта 2019

Синтаксис class в основном просто сахарное покрытие.JavaScript по-прежнему использует прототипы под капотом для методов экземпляра.Итак, несмотря на то, что вы создаете ограниченный член внутри класса.Hello - это глобальный объект, содержащий abc, и даже k не будет в его цепочке прототипов.

Хорошая статья об информации здесь

...