Inline completion and chat
Lesson 3 of 12
3Inline completion and chat
The two modes you will use most, with a real exercise showing how an innocent “improvement” silently changes behaviour.
What the picture shows: You type the start of the function, the rest of the line appears in grey, and Tab accepts it. Reading before accepting is the whole habit.
Map of this part
The concepts in order, click any one to jump to it:
Two ways into the same idea
Inline completion is like a friend finishing your sentence as you speak: quick and handy, but sometimes not what you meant. Chat is turning to them and asking "explain this to me". The danger is accepting an innocent-looking "improvement" that actually changed the meaning, which only a test reveals.
Inline completion suggests code from the context around the cursor and you accept it with Tab. Chat understands, explains and rewrites within files you choose. The exercise shows how rewriting a nested function changes its behaviour in an edge case, which is why you write a test that pins the behaviour before accepting any suggestion.
Required fundamentals
Part two
A working editor and add-on. If no grey text appears and chat does not reply, finish the previous part first.
JavaScript basics
Knowing that if is a condition and return returns a value is enough. The exercise is about the shape of code, not the language.
A willingness to test
The most important lesson here only lands if you run both versions and compare. Reading alone will not reveal it.
Core concepts
These two modes are what you will use daily. Task two has you try both on one piece of code, and underneath it sits a deeper lesson than it looks.
1Inline completion: a silent suggestion
You type, and faint grey text appears ahead of the cursor finishing what you started. Press Tab and it is accepted; keep typing and it disappears. No discussion, no justification, a silent suggestion.
What it is good at: imports, function skeletons, familiar loops, predictable names. What it gets wrong: anything that depends on your intent. The model guesses from pattern, not from understanding.
2Chat: the understanding mode
The side panel is fundamentally different: here you ask, read and argue. And it sees the open file, so "rewrite this function to read more easily" has context.
The practical difference: completion writes, chat explains. Using chat to ask "why?" after every suggestion is what turns the tool from a doer into a teacher.
3The exercise: the nested function
The project hands you this function and asks you to have chat rewrite it "without changing what it does". That last clause is the whole point.
// snippet.js - a small function that needs cleanup
function checkUser(u) {
if (u.age > 18) {
if (u.subscribed == true) {
if (u.country != "FR") {
return true;
} else {
return false;
}
}
}
return false;
}Its problems are visible: three levels of nesting, a redundant else { return false; }, and a u that explains nothing. The model will suggest something close to this:
// what the AI typically suggests: flat, readable, named
function isEligible(user) {
const isAdult = user.age > 18;
const hasSubscription = Boolean(user.subscribed);
const isOutsideFrance = user.country !== "FR";
return isAdult && hasSubscription && isOutsideFrance;
}Far clearer: flat, named conditions, the logic on one line. But does it do the same thing?
4The test that exposes the difference
On ordinary cases: yes, identical.
$ node snippet.js
{"age":30,"subscribed":true,"country":"SA"} -> true | true same
{"age":30,"subscribed":true,"country":"FR"} -> false | false same
{"age":17,"subscribed":true,"country":"SA"} -> false | false same
{"age":30,"subscribed":false,"country":"SA"} -> false | false same
{"age":19,"subscribed":1,"country":"US"} -> true | true same
{"age":18,"subscribed":true,"country":"US"} -> false | false same
behaviour identical: trueOn stranger ones, and these occur in real data, no:
$ node edge-cases.js
{"age":30,"subscribed":"yes","country":"SA"} checkUser: false | Boolean(): true DIFFERENT
{"age":30,"subscribed":2,"country":"SA"} checkUser: false | Boolean(): true DIFFERENT
{"age":30,"subscribed":"1","country":"SA"} checkUser: true | Boolean(): true same
"yes" == true -> false
2 == true -> false
Boolean("yes") -> true
Boolean(2) -> trueThe reason: x == true in JavaScript is not "is the value truthy?". It converts both sides to numbers, so true becomes 1 and "yes" becomes NaN, and they do not match. Boolean(x), meanwhile, does ask "is this truthy?" and accepts any non-empty string and any non-zero number.
5The faithful rewrite
If "without changing what it does" is meant literally, the correct version keeps the comparison as it was:
// the faithful rewrite: same shape, same behaviour
function isEligible(user) {
const isAdult = user.age > 18;
const hasSubscription = user.subscribed == true; // kept on purpose, not a typo
const isOutsideFrance = user.country != "FR";
return isAdult && hasSubscription && isOutsideFrance;
}The comment is not decoration: without it, someone will "fix" == into === and reintroduce the bug. Deliberately odd code needs a line saying why.
How it works
Two pictures: choosing a mode and its risks, then the two versions' behaviour on the same values.
Diagram 5, When to use each mode, and where the mistakes enter: accepting unread, and moving on without understanding.
Diagram 6, The same inputs through both versions: they agree on ordinary cases and diverge on truthy values that are not true.
What is actually asked of you
Task two, step by step
1. Create snippet.js in VS Code and paste the original code exactly as it is.
2. Try completion. Put the cursor below the function and start typing function describeUser(u) {, then wait a second. Grey text appears, read it before you press Tab.
3. Try chat. Open the side panel, paste checkUser and ask: "Rewrite checkUser so it is easier for a beginner to read, without changing what it does. Explain your changes in plain English."
4. Ask follow-ups until you understand every change. Ask specifically: "Is Boolean(u.subscribed) equivalent to u.subscribed == true in all cases?", and watch the answer.
5. Test it yourself. Write five cases, run both versions, compare. This step is not in the project brief, and it is the most important one: without it you believe the rewrite is equivalent.
Myth vs. reality
| The myth | The reality |
|---|---|
| “If the code is clearer, it is more correct.” | Clarity and correctness are different. The rewrite above is clearer and changes behaviour. Test first, then judge. |
| “The model knows my intent from the code.” | It guesses from pattern. That is why it suggests plausible things that assume what your project does not have. |
“x == true and Boolean(x) are the same in JavaScript.” | == converts both sides to numbers; Boolean asks about truthiness. "yes" == true // false but Boolean("yes") // true. |
| “Inline completion is faster, so it is always better.” | Faster to type, not to understand. For anything needing a decision, chat is better because it explains. |
| “Accepting one suggestion unread does no harm.” | It harms cumulatively: unread accepted suggestions build a project you do not know how to operate, and then the first bug arrives. |
| “As long as it works, there is no need to test odd cases.” | Odd values come from real data: web forms return strings, and APIs return 1 or "true" instead of true. |
Try it yourself
You asked chat to rewrite a function "without changing what it does" and got a clearer version. What next?
Asking "are you sure?" produces reassurance, not evidence, and the model will usually confirm. The only evidence is running both versions on the same inputs, including the odd ones. In this specific case they agree on ordinary values and diverge at subscribed = "yes" and subscribed = 2.
Quick review flashcards
x == true mean in JavaScript?"yes" == true = ?false, because "yes" becomes NaN and true becomes 1.Check your understanding
1. Explain in one sentence why "yes" == true // false while Boolean("yes") // true.
== converts both sides to numbers: true becomes 1 and "yes" becomes NaN, and any comparison with NaN is false. Boolean instead asks about truthiness, and any non-empty string is truthy.
2. When is inline completion genuinely better than chat?
When you know exactly what you want to write and want it faster: imports, a function skeleton, a familiar loop. It saves typing, not thinking, which is why it is excellent for repetition and poor for decisions.
3. (Spot the bug) You accepted a grey suggestion and now the program says a function is undefined. What is most likely?
The model called a plausibly-named function that does not exist in your project, or exists with a different signature. This is the commonest completion failure, which is why you read before Tab.
4. You asked "are you sure?" and the model confirmed. Is that evidence?
No. A model's confidence is not a measure of its correctness; it predicts convincing text rather than checking reality. The only evidence is running the code. Ask for a test, not for reassurance.
5. (Decision) A teammate uses only completion and says chat is slow. What do you tell them?
That they are using one tool for two jobs. Completion is excellent when you know the destination, but when they hit a bug they do not understand, chat is faster than guessing at suggestions. The real difference: completion makes you type faster, chat makes you understand more, and whoever understands more needs to type less.
Resources for this part
Sorted by kind: start with the official docs when you want the precise reference, or with an article or video when you want the explanation first.