为什么Typescript编译器不推断实例变量的作用域?

时间:2019-06-16 19:27:47

标签: typescript

编辑

这不是重复项。链接的问题是询问为什么 ES6 规范没有隐式定义“ this”。这不是这里要问的。

这里的问题是为什么Typescript编译器不适应该事实,更具体地说,原因是技术性的?

结束编辑

忽略诸如设计者偏好之类的原因,在下面的示例中是否存在防止Typescript编译器自动将local_variable映射到this.local_variable的技术问题?

import { Component, Input, OnInit } from '@angular/core';
@Component({
  selector: 'app-example',
  templateUrl: './app-example.component.html',
  styleUrls: ['./app-example.component.css']
})
export class ExampleComponent implements OnInit {
  @Input() local_variable: any;

  constructor() { }

  ngOnInit() {
    if (local_variable) {
      console.log(local_variable);
    }
  }

}

在像C ++或Java这样的语言中,人们会期望编译器推断local_variable的范围,但是在Typescript中,编译器会抛出错误TS2663,抱怨它Cannot find name 'local_variable'. Did you mean the instance member 'this.local_variable'?

为什么?为什么我们坚持看似多余的“ this”?

----

由于我现在无法添加另一个答案,因此我将题为@webstrand的个人的答复留给问题正文中Typescript gitter中提出的同一查询。

webstrand @webstrand 15:29
Typescript, once you remove the type annotations, must be completely compatible with regular javascript. This is one of the project's major guidelines.
There are a few exceptions, such as enum and namespace. But they're dead simple to transpile.
So, since the underlying javascript doesn't infer this, Typescript can't either.
@l4cr0ss Historically, the reason why javascript require the seemingly redundant this is because of an old mis-feature: with.

Jefferson Hudson @l4cr0ss 15:36
Ok. I understand that, thanks. Now, you say there are a few exceptions which are allowed because they are simple to transpile. Is it the case that such resolution could be implemented as part of the transpilation process, but because of its complexity the choice is made not to? Or, would it really break something?

webstrand @webstrand 15:42
@l4cr0ss One of the features of typescript, used by some really large projects, is that it can "transpile" directly to javascript without resolving and checking all of the types. So the compiler must be able to compile to javascript without any type information at all. To correctly infer this in all cases would require that the compiler always have type information available.

webstrand @webstrand 15:43
This is a really reassuring feature to have in an ecosystem like Javascript where there's so much churn in projects. IF typescript dies in a year, I can run all of my code through the transpile process and get back pure javascript
In fact, typescript has a type-checking mode where all the type information is stored as jsdoc-style comments.
Obviously, in that case, you can't use enum or namespace either.
As a side note , use of namespace is usually frowned upon. It comes from an era before ES supported modules natively.

2 个答案:

答案 0 :(得分:1)

我不确定为什么要用这种方式设计Typescript(您必须问MS),但是我可以做出有根据的猜测。

我认为这是因为Javascript具有动态特性。您发布的代码是有效的Javascript。在普通JS中,它将在全局范围内查找local_variable,例如window。那将是有效的,并且运行得很好。

如果Typescript通过将其解释为this.local_variable突然改变了这种行为,那么这可能会使开发人员感到困惑,并可能破坏现有代码。

答案 1 :(得分:1)

编译器错误消息很清楚,不是吗?编译器确实推断您可能的意思是this.local_variable。至少在wvteijlingen的回应中指出,没有该名称的全局变量。

设计人员可能已经猜出了定义。但是,报告错误并让您准确地表达 的含义要比定义一种行为(如果在您的意图不是那样时会引起难以发现的问题)更好。

当您考虑一项作业时,这一点更加明显:local_variable = 0
更有可能是您忘记键入this.还是忘记了键入let