В настоящее время используется машинопись 3.4.5 с включенным режимом strict
...
Предыстория
Я просто столкнулся с ситуацией, когда машинопись не защитила меня от моих собственных ошибок, к сожалению. И я пытаюсь выяснить, почему машинописный текст не смог поймать эту ошибку.
Я писал объявление типа для такой функции:
function acceptVisitors (visitor) {
visitor.apply(value);
}
Проницательные наблюдатели могут указать, что тип visitor
может быть определен одним из двух способов - как функция или как объект со свойством apply
:
type visitorType = (this: IValue) => void;
// or
type visitorType = {
apply: (value: IValue) => void;
};
Оказывается, в моем случае это был последний. После добавления объявления типа я приступил к написанию этого неправильного кода:
// This is incorrect because it doesn't pass it as an argument.
// Rather, the `this` context is set to the value.
acceptVisitors((value: IValue) => { ... });
Теперь, загадкой является то, что Typescript не показывал ошибку, когда я передавал функцию, тип которой был несовместим с visitorType
.
Упрощенный пример
Давайте изменим тип параметра на строку и пройдемся по ней.
Я определяю тип с именем func
, который является функцией, требующей строкового аргумента.
type func = (param1: string) => void;
Функции по своей природе являются вызываемыми объектами, которые также имеют метод apply.
declare let f: func;
f.apply(undefined, ['str']);
// all good
Теперь вот другой тип - объект со свойством apply
.
type objectWithApplyProp = {
apply: (param1: string) => void;
};
Мы можем вызвать свойство apply, но не так ...
declare let o: objectWithApplyProp;
o.apply(undefined, ['str']); // Error: Expected 1 arguments, but got 2.
И objectWithApplyProp
имеет подпись вызова, которая не работает с func
:
o.apply('str'); // ok
f.apply('str'); // Error: The 'this' context of type 'func' is not assignable to
// method's 'this' of type '(this: string) => void'
И дальнейшие тесты показывают, что f
присваивается o
, но не наоборот, что имеет смысл ... все функции являются объектами, но не все объекты могут быть вызваны.
Но почему f
считается присваиваемым o
? Тип objectWithApplyProp
требует значения apply
, которое соответствует определенного типа , а func
не соответствует
Подпись apply
функции должна быть выведена из ее параметров, но машинописный текст, по-видимому, не выводит ее.
Итак, любые отзывы приветствуются. Я не прав или есть ограничение в Typescript? Это известная проблема? Спасибо