
VS Code to autocomplete JavaScript class 'this' properties automatically - velmu
https://react-etc.net/entry/vs-code-to-autocomplete-javascript-class-this-properties-automatically
======
zbentley
The most important word in the title is "class". It only does this properly
for JS code inside an explicit ES6 class, and, after some cursory testing,
doesn't work too well if you bind things to the class at runtime/outside of
the main class block.

VS code doesn't autocomplete "this" for "old-school" (function-provided "this"
objects and manual prototype inheritance etc.) object-orientish JS; it doesn't
compute it properly or at all for re-bound "this" (e.g. apply()/bind()).

Making autocompletion analysis work for non-straightforward non-ES6 OO
javascript is a very hard (maybe impossible even without any "eval"ed code,
though I'm not sure) thing to do, so this isn't a ding on VS code: any
autocompletion is better than none.

That said, if the only way to get good OO-code autocompletion is to reduce the
subset of the language/OO models usable to basically "what you could have in
Java/C#", it might be a good opportunity to re-evaluate your choice of
language. Transpilers for more easily-statically-analyzable languages do
exist, after all.

~~~
paulgb
> ...it might be a good opportunity to re-evaluate your choice of language.
> Transpilers for more easily-statically-analyzable languages do exist, after
> all.

I find TypeScript does a pretty good job of allowing as much static analysis
as you want without preventing you from using all the features of JS that
break it if you wish. In an ideal world I'd work in a fully static language
that transpiles to JS but the reality is it's usually necessary to deal with
legacy JS libraries. I haven't seen a fully static transpiled language deal
with that gracefully, but I'd love to be wrong about that!

~~~
sjrd
> I haven't seen a fully static transpiled language deal with that gracefully,
> but I'd love to be wrong about that!

Scala.js is specifically designed to be very good at this. You might want to
give a shot, if you haven't already ;) Usually you would stay within the type-
safe Scala code, or even talk to JavaScript libraries in a type-safe way. But
it will always let you do anything you could do in JavaScript (it is one of
its core language design decisions). If you want to do something especially
weird, the syntax to do so might be pretty awkward, but in most cases it will
feel very natural.

~~~
kbp
In ReasonML, most of your code is just Reason (which is just OCaml), but you
can easily provide type declarations and use Javascript code in a typesafe
way, or you can just drop to raw JS at any point in a Reason file.

------
tootie
Not to be a grump, but if you were using a staticly-typed language with any
half-baked IDE 20 years ago, this behavior was available.

~~~
ts330
hard to fathom there's an entire generation of developers out there for whom
this is entirely new magic. there's an entire class of problem and suite of
(bad) tooling that they're having to grapple with to deal with things that
simply aren't issues in statically typed languages.

~~~
davedx
As someone who spent a good 8 years doing development in static languages and
then the next 8 or so doing mostly JavaScript, I do occasionally miss the
superior tooling available in static languages - and yet, I’m more productive
in dynamic languages. This isn’t just experience, I occasionally still write
Java and Scala code. But dynamic languages are sufficiently more powerful that
the trade off with tooling is worth it.

In Scala the compile time alone is a massive drag.

~~~
bitwize
Are you more productive according to the stopwatch? Or do you just _feel_ more
productive?

I believe that a strong static type system with generics is an unmitigated
win, and that any time you think you may have lost fighting the compiler is
more than regained by the time saved not having to track down type bugs at
runtime, using the IDE to perform code completion and refactoring, etc. This
effect is magnified as the project grows large.

------
projectramo
Can someone explain why this (can't stop those puns) is a big deal?

1\. I mean why hasn't it existed before? Surely an editor can figure out which
object you're in and auto-complete _this_ on the basis of that.

2\. If it is hard for some reason, how did they do it?

~~~
_sdegutis
The value depends on how you call the function at runtime which requires much
deeper code analysis than something like syntax highlighting.

~~~
vbezhenar
I think that the best editing experience would be editor combined with
debugger. JavaScript is a dynamic language, a lot of autocompletes before run
is just guesses. But if you're running program and stopped it at that line,
you know all available objects and their properties, so autocomplete would be
perfect. It would require a bit different development style, but it might
worth it.

~~~
chatmasta
Problem is enumerating all the possible code paths that could break at the
current line.

~~~
vbezhenar
That's developer problem. I'll provide input values for needed use-case myself
(for example with unit test or just manually) and IDE should stop at given
line and provide autocomplete. I don't think that there's implementation
difficulty, it's just a bit different style of coding, but it should work very
well with test driven development.

------
k__
I was blown away how well VSC interacts with JS, especially autocompletion via
imports.

~~~
softawre
It's built in and for TypeScript. It uses .d.ts files for JS completion. And
yeah, it's great.

~~~
k__
AFAIK TypeScript has a JavaScript mode too?

------
mattbierner
VS Code JavaScript/Typescript extension dev here

Yes this feature is completely obvious in hindsight, so much so that I felt a
little silly highlighting that we never did it before. I guess sometimes you
just need someone to file a feature request to point this type of thing out

Anyways, please try it out in the current VS Code insiders builds and VS Code
1.20 once it is released next week. Lots of much more exciting stuff coming in
1.20 as well

------
rictic
By itself this isn't very impressive, but there's more context in the wings if
you pay careful attention to the TypeScript type system. Take a look at
[https://github.com/Microsoft/TypeScript/pull/21316](https://github.com/Microsoft/TypeScript/pull/21316)
and
[https://github.com/Microsoft/TypeScript/pull/21496](https://github.com/Microsoft/TypeScript/pull/21496).
This, combined with the existing literal types and mapped types, allows the
TypeScript compiler to understand a huge set of existing practices in the
JavaScript world, and do high quality type inference over code that looks
totally untypable.

For example, this is a pattern I see a lot:

    
    
      const args = parseCliFlags({
        help: {
          parser: Boolean,
          description: 'whether to show help',
          short: 'h',
        },
        custom: {
          parser: (v: string) => {return {hmmm: 'yes'}},
          repeated: true
        }
      });
      if (args.help) {
        console.log('help screen!');
      }
      for (const custom of args.custom) {
        console.log(custom.hmmm);
      }
    
    

So we produce an args object based on the descriptors passed into
parseCliFlags. Specifically, we use the parser function and the repeated
field. With the above PRs, this code can be fully type checked:

    
    
      interface Descriptor {
        readonly parser: (value: string) => any;
        readonly description?: string;
        readonly short?: string;
        readonly repeated?: true;
      }
      interface Descriptors {
        readonly [flag: string]: Descriptor;
      }
      type FlagTypes<T> = { [K in keyof T]: FlagTypeOf<T[K]> };
      type ReturnTypeOf<V> = V extends (...args: any[])=>infer R ? R : never;
      type FlagTypeOf<V> = V extends {repeated: true, parser: (val: string)=> infer R} ? R[] : V extends {parser: (val: string)=> infer R} ? R : never;
    
    

That code is tricky to write, but it only needs to be written once, and
submitted to DefinitelyTyped. From that point, every VSCode user could benefit
from these typings (they already have this part working today, with typings
for your node libraries downloaded automatically from DefinitelyTyped).

------
irq-1
The feature does not know the type of "this".

It doesn't complete "this." but rather when you type a member variable it
inserts "this.member". ex. type "width" and it replaces it with "this.width".

~~~
brlewis
Got a link to more info on the feature? This article seems uninformative at
best.

------
nkkollaw
Perhaps unrelated, but JavaScript has the most annoying handling of "this" in
classes that I've ever seen.

I'm constantly typing "bind(this)", while the default case should be that
"this" within a class points to the object.

I understand backward compatibility, but I wish there was some command I could
add at the beginning of the file to make JS behave normally. Kind of like "use
strict".

------
ajeet_dhaliwal
_this_ is great. But seriously, this is my setup for 75% of my work, Visual
Studio Code with JS, excited to see this little feature in action.

------
htsh
How does this compare to Webstorm's autocomplete functionality (as it's one of
the primary reasons I started using WS years ago)?

------
koolba
Is this new feature specific to vanilla JS classes? I've been using
autocomplete for Typescript classes in VS Code for as far back as I can
remember.

~~~
supergreg
Edit: I misinterpreted the question at first. I guess in TS you declare a
class' properties explicitly while in javascript it is usually done in the
constructor. The feature must be related to these dynamic properties. Original
answer below.

This[0] page says _this_ problem can be also seen in Typescript. But TS has
the _arrow function as a class method_ feature that in Javascript is only at
stage 2 in it's way to standardization, so it's easier to solve there.

[0] [https://github.com/Microsoft/TypeScript/wiki/'this'-in-
TypeS...](https://github.com/Microsoft/TypeScript/wiki/'this'-in-TypeScript)

------
partycoder
I don't think this title is correct.

`this` is the receiver of the function, which can change depending on how the
function is invoked, scope, etc.

------
austincheney
Madness. Code is so much cleaner when developers drop "this" from their code.

~~~
paulgb
Unlike Java, JavaScript requires "this".

Edit: I didn't realize this would be a contentious point! I'm not trying to
advocate for any particular style of JavaScript, just making the point that
places in Java where "this" can be omitted, in JavaScript it cannot.

~~~
dentemple
It does not.

Certain frameworks will encourage more of its use (such as with passing
functions-as-props in React), but Javascript itself can support multiple
paradigms, with the `this` keyword supporting only some of its messiest parts.

~~~
paulgb
Is this true even with classes defined with the "class" keyword? I just tried
it and I can't access fields without "this."

~~~
dragonwriter
The “class” keyword was added fairly recently to simplify Java-style OO
programming in JavaScript; it's true that that _style_ of programming requires
extensive use of “this” in JS, specifically because, unlike Java, JavaScript
is not designed from the ground up to favor that style exclusively.

Java will probably always be a better language for writing Java than
JavaScript is, but the Java-in-browsers story has sucked for a long time, so
we’re stuck with people who want Java using JavaScript as Java.

~~~
heavenlyblue
So how is JavaScript supposed to be used then?

~~~
LaGrange
Reluctantly.

