
If you’ve ever used ng-template
in Angular, you know how powerful it is for building dynamic, reusable UI components. But here’s the catch: type safety goes out the window. You’re left guessing what’s available in the template context, and IDEs can’t help much. That’s where the TypedTemplateDirective
comes in — a simple trick to lock down your templates with strong typing.
In this post, I’ll walk you through how I use this directive to make ng-template
just as type-safe and developer-friendly as the rest of Angular.
🧠 What Is TypedTemplateDirective
?
It’s a lightweight structural directive that lets you explicitly type the context of an ng-template
. Once typed, your editor understands the available variables, so you get proper autocompletion, type checking, and overall peace of mind.
🔧 The Implementation
Here’s the directive code I use:
import { Directive, Input, TemplateRef } from '@angular/core';
@Directive({
selector: 'ng-template[typedTemplate]',
})
export class TypedTemplateDirective<T> {
@Input() typedTemplate: T;
constructor(private contentTemplate: TemplateRef<T>) {}
static ngTemplateContextGuard<T>(
dir: TypedTemplateDirective<T>,
ctx: unknown
): ctx is T {
return true;
}
}
🔍 How It Works
@Directive(...)
: Tied specifically to<ng-template>
usingng-template[typedTemplate]
.<T>
: Makes it generic — it’ll work with any shape of data you want to pass.typedTemplate
input: Binds your context so Angular knows what to expect.TemplateRef<T>
: Gives Angular access to the actual template.ngTemplateContextGuard
: This is the secret sauce — it lets Angular and TypeScript infer types for thelet-
variables inside the template.
🚀 How I Use It in a Component
Let’s say I have a component with a FormControl
and a string parameter:
import { Component } from '@angular/core';
import { FormControl } from '@angular/forms';
@Component({
selector: 'app-example',
templateUrl: './example.component.html'
})
export class ExampleComponent {
typeToken = {
control: new FormControl(''),
param: 'Hello, Angular!'
};
}
And now in the template:
<ng-template
#myTemplate
[typedTemplate]="typeToken"
let-control="control"
let-param="param"
>
<input [formControl]="control" />
<p>{{ param }}</p>
</ng-template>
✨ Boom! Your template now has full type awareness of control
and param
. No more any
context or accidental undefined values.
✅ Why This Is a Game Changer
- Strong Typing in your templates.
- Autocomplete for
let-
variables. - Zero runtime surprises.
- IDE-friendly — full IntelliSense support inside
ng-template
. - Reusable — works with any object, across any component or module.
💡 Bonus: Works Great with Reusable UI Components
If you’re building reusable table cells, dynamic form fields, or dialog templates, this directive gives you confidence your inputs are exactly what your template expects — and nothing more.
🧩 Final Thoughts
Angular templates are incredibly powerful, but they’ve always lacked strict typing — until now. With this little directive in place, your ng-template
usage becomes safer, smarter, and much more maintainable.