5 ms·
If the code isn't typed, then you can't find all references accurately. For example, in the below, you've no idea if the "a" inside the function is the same is
by billti 10y ago
If the code isn't typed, then you can't find all references accurately. For example, in the below, you've no idea if the "a" inside the function is the same is as on "foo".
```javascript
var foo = {
a: true, // Find all references on "a" here...
b: "hello"
};
foo.a = false;
bar(foo);
function bar(obj) {
obj.a = false; // Won't find this "a".
}
```
Call site inference can follow this sometimes. However with types it can be certain, e.g.
```typescript
interface Foo {
a: boolean;
b: string;
};
var foo: Foo = {
a: true, // Find all references on "a" here...
b: "hello"
};
foo.a = false;
bar(foo);
function bar(obj: Foo) {
obj.a = false; // Will be found, renamed if refactored, etc..
}
```
Note that the JavaScript in VS Code is powered by the same engine as the TypeScript, so it's using the same inference, it just can't infer untyped parameters.
There is some support for JsDoc in the engine, so code like the below will work:
```javascript
/** @typedef {{a: boolean, b: string}} Foo */
/** @type {Foo} */
var foo = {
b: "hello"
};
foo.a = false; // Find all refs here
bar(foo);
/**
* @param {Foo} obj - Some object
*/
function bar(obj) {
obj.a = false; // will find this one
}
```
Full disclaimer: I work on these tools.
- ggregoire 10y agoNice catch! Yeah, that makes sense. As you work on this, do you know if the refactoring tools would fully work with my code typed with Flow instead of TypeScript? (I use the official flow-for-vscode extenstion, idk if it's relevant) Edit: Ok I just tried and it works, even with the extension disabled. type Foo = { a: boolean, b: string, } var foo: Foo = { a: true, // Find all references on "a" here... b: "hello" }; foo.a = false; bar(foo); function bar(obj: Foo) { obj.a = false; // Found it. }
- billti 10y agoI don't know, but generally call-site inference has a couple of notable issues: - If you don't have any calls to the function yet (i.e. "bar(foo)" wasn't there above), then there is nothing to infer from, so you have no idea what the type is at this point (other than by the use of the parameter inside the function). - Is your call-site wrong? If the parameter type is explicit, this is easily checked. If not, then again you can only go by what the function does with it. (Which may not be much help if it's something like "RestAPI.post(JSON.stringify(theParamInQuestion))" ).
- z3t4 10y agoThank you for actually providing an argument for having types. The parser could however in-line the function and replace obj for foo. I do advocate using the same variable names for function arguments though, as having different names for the same variable is not only hard to refactor, it's also very confusing! So instead of using "that", me, myself, obj, str, etc, use the actual variable name! Disclaimer: I'm working on a competing tool
- friendzis 10y agoEither I do not understand your point or you are walking a thin line. If a particular function can be tied to particular variable from scoping block, then the function is not entirely useful. On the other hand, if a function is general and has the same argument name as variable from scoping block, which is going to be passed in, mentally it is difficult to analyse the function without thinking about the variable which may shadow bugs in function. E.g. square root function may omit negative argument check, because variable from scoping block is always positive. Instead of knowing scoping rules I advocate for distinct variable names, so scoping rules (name shadowing) do not even come into play.
- z3t4 10y agoI think the problem has to do with object oriented programming and classes. Like when you have an Apple that inherits from Fruit, witch later starts looking like a Banana. With prototype you do not have that problem as you copy-paste code instead of couple code. When you rename a variable and have to search more then one function or file, then there are bigger problems with your design, because you are basically using a global variable, even though it's praised as a module. Now does your refactor tool also fix documentation and other peoples code that depends on yours ? function Person(name) { var person = this; person.name = name; } var person = new Person("Jon Doe"); alert("Welcome " + person.name); person.name = "Harry Houdini"; // ES6 example: var messages = people.map( person => person.name += " is a rock star" )
- faceyspacey 10y agoQuestion: How close is Flow coming within VS Code to parity with the features available to TypeScript?