Стратегия вывода this в TypeScript меня сбивает с толку, например:
class A {
s: String
constructor() {
this.s = "this is fine"
}
f() {
console.info(this.s)
}
}
let a = new A
a.f() // -> this is fine
let f1 = (new A).f
f1() // -> undefined
Если вы поместите код в TypeScript Детская площадка и проверите тип this внутри f(), вы увидите, что он предположительно относится к типу this: this, что означает подтип A.
В этой ситуации, я думаю, это означает, что this привязан к A и не может ссылаться на глобальный объект. В противном случае следует предполагать, что this относится к типу this: Any.
Но на самом деле, как показано при вызове f1(), если функция f вызывается вне контекста A, она все равно может быть глобальным объектом.
Поэтому, на мой взгляд, предполагаемый тип this внутри f() должен быть this: Any, а не this: this. И только если функция f определена с помощью стрелочной функции, она может быть выведена как this: this. Например:
class A {
s: String
constructor() {
this.s = "this is fine"
}
f = () => {
console.info(this.s)
}
}
let a = new A
a.f() // -> this is fine
let f1 = (new A).f
f1() // -> this is fine
Итак, это ошибка или особенность дизайна? Как TypeScript на самом деле определяет тип this?
@JaromandaX Спасибо за советы. Я понимаю, что this определяется контекстом на сайте вызова динамически, в некотором порядке приоритета, как показано в некоторых статьи. Но я хочу знать, как TypeScript статически определяет тип this.
Извините, теперь я понимаю, о чем вы спрашиваете ... поскольку машинописный текст набран, вы хотите знать, как машинописный текст знает, какой тип this в любой момент
@JaromandaX Да, это именно то, что я хочу знать. Потому что в приведенном мной примере поведение мне противоречит.
@mpm Я пробовал, это объект Window в Chrome: код
Добавлю, что это предложение выдает ошибку компиляции на let f1 = (new A).f.
@MattMcCutchen Эта ссылка кажется действительно полезной. Я прочитаю соответствующие страницы, чтобы лучше понять конструкцию типа this. Спасибо.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


So in my opinion, the inferred type of this inside f() should be this: any, not this: this.
Ну да. В чем-то ты прав. Нет 100% уверенности в том, что this внутри функции класса действительно является экземпляром класса. Но машинописный текст не должен быть на 100% точным! Это важно понимать! Типовые гарантии действуют не во всех ситуациях. Они буквально не могут.
Javascript - это динамический очень. Невозможно просто проанализировать всю эту динамику во время компиляции.
Таким образом, Typescript полностью полагается на предположения и информацию о типах, предоставленную пользователем. Это должно помочь вам, но не остановит вас, когда вы захотите выстрелить себе в ноги.
Просто никогда не делайте этого:
const x = foo.x;
x();
на самом деле это приводит к тому, что старые модели классов, а затем классы ES6, такие как объектная модель ember, очень трудно использовать с машинописным текстом - предположения просто не работают. И даже у лучших наборов есть ограничения. Есть вещи, которые вы можете делать в JS, но не можете определить в TS. Тем не менее TS может быть очень полезен во всех остальных случаях.
Отличный вопрос. В Typescript есть то, что мы называем ненадежной системой типов. (Closure Compiler и Flow также имеют ненадежные системы типов.) Неправильная система типов означает, что Typescript иногда вычисляет тип для ошибочного выражения; он отличается от типа, который выражение будет принимать во время выполнения. Как упоминалось в другом ответе, это происходит потому, что JavaScript очень динамичен, и разработчики систем типов используют несколько сокращений, чтобы уменьшить сложность.
В вашем конкретном примере, хотя this действительно может быть any, на практике это почти всегда A, так что это то, что выбирает Typescript. Однако он потенциально может выдать предупреждение на f1(), потому что метод вызывается как функция (то есть без this).
is this a bug or a design feature?предназначен для работы так же, как javascript.