Angular can be tricky at times, but the language service is one of the features that makes getting started genuinely pleasant.
What exactly is a language service?
A language service is essentially a program that takes your code as input and returns completions, errors, hints, and diagnostics on a per-file basis. It also distinguishes between syntactic and semantic issues within each file. The Angular language service performs this exact role for Angular projects, providing these insights across your entire codebase.
What kind of assistance does it offer?
Angular source files are typically named with .ts or .html extensions, which leads your code editor to assume it's dealing with standard TypeScript and HTML. However, that's not the full picture. Angular templates contain Angular-specific constructs like components, directives, and property/event bindings, which the editor doesn't recognize on its own.
This is where the language service steps in. It recognizes that you're working within an Angular project and communicates the meaning of that Angular-specific syntax to the editor, enabling proper understanding and tooling.
VS Code leverages the TypeScript Language Service and the HTML Language Service to interpret TypeScript and HTML files. Due to their widespread use, these services are bundled with VS Code out of the box.
If you launch VS Code without any additional setup and open an Angular component that uses an inline template, here's what you'll encounter:
Since the editor interprets the file as TypeScript, it doesn't apply any special formatting or highlighting to the template section. The template is treated as a plain string, even though the editor generally supports HTML (but not within the context of a TypeScript file).
Consequently, you get no support for Angular or HTML syntax. Hovering over the div, the click binding, or the **ngIf* directive won't yield any helpful information.
The Language Service informs the editor that you're inside an Angular component and instructs it to treat the template field as an Angular template—which is essentially HTML with enhanced capabilities built on top.
After installing the Angular Language Service and reopening that file, the experience is significantly improved.
Let's examine the information provided when hovering over different elements within the template.
Event bindings
Hovering over the click event reveals that it's fundamentally an addEventListener call on the div element—which is precisely what the click binding accomplishes under the hood.
The type of the $event value is shown as MouseEvent, which aligns with what an addEventListener for the click event type dispatches. There's no magic involved here 🪄!
Now, let's introduce a component that exposes an Output and incorporate it into the template.
When hovering over the onGameStart event, you can see that it's an EventEmitter that emits a boolean value, which is exactly correct.
Interpolation
When you hover over the interpolated version variable, the correct type is displayed. In this instance, version is a property of LazyComponent with a type of number. This functionality extends to more complex types as well.
The accurate type information appears because Angular templates are strictly typed. The language service uses the Angular Compiler under the hood to obtain all this data.
Data binding
Let's add an Input to the component we created earlier and pass some data to it from the LazyComponent.
The gameVersion input expects a number type, and we're passing a property of number type. Everything checks out fine.
Now, let's modify the property on LazyComponent to be a string type and observe the outcome:
As anticipated, an error is raised, indicating that the type of the property being passed doesn't match the type the input requires.
Directives information
The template contains an **ngIf* directive. Hovering over it reveals the class it originates from and its generic type, which in this case is a boolean. Therefore, you need to pass a boolean expression to the **ngIf* directive.
Next, let's add an NgFor directive and see what details the editor provides.
The editor will display the directive class as NgForOf along with its generic types. So far, so good!
These are just a few examples of the information the language service provides.
But there's more, yay 🥳!
Go to definition
You can right-click on any item in the template and select Go to definition, and it will navigate you there! This works for components, directives, inputs, events, DOM elements, and more.
As demonstrated, it navigates to the correct location—whether that's within your own components and directives, ones provided by Angular, or the type definitions for DOM elements found in files like lib.dom.ts.
Go to references
The Go to references option is also available. It displays every location where the item you're searching for has been used!
Rename symbol from template
Since everything in Angular is TypeScript at its core, the Rename symbol feature can be used directly within a template, and all references to that symbol will be updated accordingly. This applies to inputs, outputs, class properties, methods, and more.
The Rename symbol functionality might not work perfectly if initiated from inside the class rather than from the template. This is due to an unresolved issue in VS Code itself.
Code autocompletion
When you begin typing within the template, the language service supplies VS Code with autocompletion suggestions. This includes inputs, outputs, events, class properties, and more.
Code fixes
The most recent iteration of the Language Service introduces code fixes. You can generate properties or methods directly from the template, or correct things that may have been written incorrectly.
Notice that it not only creates the method but also infers and sets the type of the event passed to it—in this case, it was MouseEvent.
Angular language service has seen significant evolution. It was completely rewritten from the ground up in anticipation of the Ivy compiler, and that effort was well worth it. We now have access to all these capabilities that weren't feasible before.
There's also a lot of exciting functionality on the horizon, such as importing components, directives, and pipes for Standalone components as well as NgModules.
In the meantime, go install the language service (if you haven't already) and take full advantage of it—it has a great deal to offer and will make your coding experience much smoother!











