ng-template - typed variable

There is an easy workaround to get the IDE to play along and also have code completion using a user-defined type guard:

Create a function in your class which takes the variable as an argument and returns the same variable:

export class CardComponent {
  ...
  public video = (item: Video) => item;
}

Now simply wrap the variable in your template with the function:

<h5 class="tile__type">{{video(content).type}}</h5>

I created a helper directive to solve this.

import { Directive, Input, TemplateRef } from '@angular/core';

@Directive({selector: 'ng-template[typedTemplate]'})
export class TypedTemplateDirective<TypeToken> {

  // how you tell the directive what the type should be
  @Input('typedTemplate')
  typeToken: TypeToken;

  // the directive gets the template from Angular
  constructor(private contentTemplate: TemplateRef<TypeToken>) {
  }

  // this magic is how we tell Angular the context type for this directive, which then propagates down to the type of the template
  static ngTemplateContextGuard<TypeToken>(dir: TypedTemplateDirective<TypeToken>, ctx: unknown): ctx is TypeToken{ return true; }
}

Use it like this

<!-- typedTemplate is the directive, typeToken is an object on our component -->
<ng-template #someTemplate [typedTemplate]="typeToken" let-param="param">
  {{param}}
</ng-template>

And in the component

// here we create typeToken. the value doesn't matter as it's never used, but the type of this variable defines the types of all template parameters. 
typeToken: { param: string };

There is no type inference for let-* variables. The let- context is part of the micro syntax parser for Angular, and an IDE can not infer the type as there is no clear origin.

https://gist.github.com/mhevery/d3530294cff2e4a1b3fe15ff75d08855

You can try to silence the IDE warning using $any()

https://angular.io/guide/template-syntax#the-any-type-cast-function

<ng-template #tileTemplate let-content>
  <h5 class="tile__type">{{$any(content).type}}</h5>
</ng-template>

You can force type inference by using a function

<ng-template #tileTemplate let-content>
  <h5 class="tile__type">{{toVideo(content).type}}</h5>
</ng-template>

public toVideo(value: any): Video { return value as Video; }