функция, чтобы объявить это явно. Но, по-видимому, это больше связано с тем, что функция осознает тип структуры встраивания, чем следит за потоком объектной модели. И это не помогает в моем случае.
периментирую с поведением, которое мне кажется странным.
Давайте рассмотрим следующий пример (проверить это на площадке Typescript):
abstract class FooAbstract {
abstract bar() {}
}
class Foo extends FooAbstract {
bar() {
return { bar: 'bar' };
}
}
class FooMaker<FOO extends FooAbstract> {
constructor(public foo: FOO) {}
bar() {
return this.foo.bar();
}
baz = () => {
return this.foo.bar();
}
}
let foo = new Foo();
let result = foo.bar();
let foomaker = new FooMaker(new Foo);
let foo2 = foomaker.foo; // Type "Foo", OK
let result1 = foomaker.foo.bar(); // Type "{bar: string}", OK
let result2 = foomaker.bar(); // Type "{}", ???
let result3 = foomaker.baz(); // I've seen comments about using a lambda... Not better
result2
а такжеresult3
набираются как аннотацияbar
функция ({}
). Кажется, чтоthis
не разрешен как конкретный классFoo
но как абстрактный классFooAbstract
, В то время как типfoo2
показывает, что классfoo
свойство решено правильно.
Что здесь происходит? Я делаю что-то неправильно?
ОбновитьКак запоздалая мысль, этот случай можно переформулировать так (Проверьте это на игровой площадке Typescript):
class Foo {
bar() {
return { bar: 'bar' };
}
getThis(): this {
return this
}
}
class Wrapper {
bar<FOO extends { bar(): {} }>(foo:FOO) {
return foo.bar();
}
}
let wrapper = new Wrapper();
let result = (new Foo()).bar();
let result2 = wrapper.bar(new Foo());
result
имеет тип{bar:string}
result2
имеет тип{}
(из интерфейса).wrapper.bar
имеет типWrapper.bar<Foo>(foo: Foo): {}
С этим образцом становится понятнее, даже если знать, чтоFOO
набирается какFoo
, Машинопись использованияFOO
определение, а не его явный тип какbar
тип возврата.
Хорошо, во время борьбы с наборами текста, я думаю, я выровнялся. Концепция заключается в том, что неявные типизации вМашинопись не следуйте какой-либо модели наследования, даже если тип выведен. Ну мне еще интересноЗачем или жеэто изменится, но мне придется справиться с "это так". Так что в этом случае тип должен быть явным.
Я нашел более простой способ написать свой пример (попробуйте это на детской площадке Typescript):
abstract class FooAbstract {
abstract bar(): {}
}
class Foo extends FooAbstract {
bar() {
return { bar: 'bar' };
}
}
class FooMaker<FOO extends FooAbstract, BAR> {
constructor(public foo: FOO & { bar: () => BAR } ) {
}
bar():BAR {
return this.foo.bar() as BAR;
}
}
let foomaker = new FooMaker(new Foo());
let result = foomaker.bar();
result
получает тип{bar:string}
и не нужно ставить дженерики везде. Материал вFooMaker.constructor
Тип параметра может стать чище, если обратиться к интерфейсу с универсальным.