Как TypeScript определяет тип this?

Стратегия вывода 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?

is this a bug or a design feature? предназначен для работы так же, как javascript.
Jaromanda X 09.09.2018 05:42

@JaromandaX Спасибо за советы. Я понимаю, что this определяется контекстом на сайте вызова динамически, в некотором порядке приоритета, как показано в некоторых статьи. Но я хочу знать, как TypeScript статически определяет тип this.

Ben 09.09.2018 05:46

Извините, теперь я понимаю, о чем вы спрашиваете ... поскольку машинописный текст набран, вы хотите знать, как машинописный текст знает, какой тип this в любой момент

Jaromanda X 09.09.2018 05:47

@JaromandaX Да, это именно то, что я хочу знать. Потому что в приведенном мной примере поведение мне противоречит.

Ben 09.09.2018 05:57

@mpm Я пробовал, это объект Window в Chrome: код

Ben 09.09.2018 06:07

Добавлю, что это предложение выдает ошибку компиляции на let f1 = (new A).f.

Matt McCutchen 10.09.2018 00:22

@MattMcCutchen Эта ссылка кажется действительно полезной. Я прочитаю соответствующие страницы, чтобы лучше понять конструкцию типа this. Спасибо.

Ben 12.09.2018 17:07
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
7
405
2

Ответы 2

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).

Другие вопросы по теме