Type-Safe ng-template in Angular — Meet TypedTemplateDirective

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> using ng-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 the let- 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.

Leave a Comment

Your email address will not be published. Required fields are marked *