2

Edit

This is not a duplicate. The linked question is asking why "this" is not defined implicitly by the ES6 specification. That is not what is being asked here.

The question here is why does the Typescript compiler not adjust for that fact, and more specifically, is the reason technical in nature?

End Edit

Ignoring reasons such as designer preference, is there a technical problem preventing the Typescript compiler from automatically mapping local_variable to this.local_variable in the below example?

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);
    }
  }

}

In a language like C++ or Java one would expect the compiler to infer the scope of local_variable, but in Typescript the compiler throws error TS2663, complaining that it Cannot find name 'local_variable'. Did you mean the instance member 'this.local_variable'?

Why? Why are we stuck with the seemingly redundant "this"?

----

As I am unable to add another answer right now, I am going to leave the response of an individual named @webstrand to the same query posed in the Typescript gitter here in the body of the question.

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.
Jefferson Hudson
  • 728
  • 1
  • 10
  • 22
  • 2
    Typescript is Javascript with types. Javascript requires `this` so typescript requires `this` – Titian Cernicova-Dragomir Jun 16 '19 at 19:35
  • "Ignoring reasons like designer preference" kind of eliminates the only possibly satisfying answer here, though. Of course it is *technically* possible for the compiler to do this... but they chose not do it for [good reasons](https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals#goals) that you don't care about. Oh well! – jcalz Jun 16 '19 at 23:16
  • @jcalz - I am not asking about designer preference for the precise reason that I am interested in understanding if there exists a *technical* barrier to the implementation. If the designers chose not to implement such a feature out of choice then that is neither here nor there, except that it means there was no a technical barrier. – Jefferson Hudson Jun 17 '19 at 01:23

2 Answers2

1

I don't know for sure why Typescript was designed this way (you'd have to ask MS), but I can make an educated guess.

I assume this is because of the dynamic nature of Javascript. The code you've posted is valid Javascript. In vanilla JS, it would look up the local_variable in the global scope, for example window. That would be valid, and it would run perfectly fine.

If Typescript would suddenly change this behaviour by interpreting it as this.local_variable, it could be quite confusing for a developer and potentially break existing code.

Rengers
  • 14,911
  • 1
  • 36
  • 54
  • I appreciate your answer and would request that you reconsider your vote to close this question as a duplicate. As I mention in my edit, this question is specifically about the nature of the Typescript compiler, while the question you linked as a duplicate is in regards to the ES6 specification. – Jefferson Hudson Jun 17 '19 at 01:55
  • I did not mark this as duplicate. I marked it as off topic, because I think that most answers would be speculation. It’s simply a design choice, and the only people that know the reasons and the people who design TS. – Rengers Jun 17 '19 at 08:53
  • 1
    But it seems you found a satisfactory answer yourself. If the question is reopened you can post that and mark it resolved. – Rengers Jun 17 '19 at 08:55
1

The compiler error message is clear enough, isn't it? The compiler does infer that you probably meant this.local_variable. At least in the absence of a global variable of that name, as pointed out in wvteijlingen's response.

The designers could have made that guess the definition. But it's better to report an error and let you write exactly what you mean, than define a behavior that causes hard-to-spot problems in cases where you didn't mean it that.

It's more obvious when you consider an assignment: local_variable = 0
What is more likely, that you forgot to type this. or that you forgot to type let?

Roland Weber
  • 3,395
  • 12
  • 26