Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to typehint IDE for "let variable" type in Typescript and Angular?

Having markup like

    <mat-cell *matCellDef="let request">
         <a [href]="request.url" target="_blank">{{request.requestId}}</a>
    </mat-cell>

Can I typehint IDE somehow that request is of type Request? I am using IntelliJ here.

Please be noted, that I am using Angular Material table here, so declaring request in component is not an option here as it is purely template variable. It contains row data provided internally by component itself on every row iteration.

Note that this is perfectly valid markup used in MatDataTable component.

like image 479
Antoniossss Avatar asked Jul 11 '18 07:07

Antoniossss


3 Answers

as the

tableDataSource: MatTableDataSource<ToDoInterface>;

does not type the model,

this:

<ng-container matColumnDef="toDo">
  <th mat-header-cell *matHeaderCellDef mat-sort-header>ToDo</th>
  <td mat-cell *matCellDef="let model">
    <ng-container *ngIf="assertItemType(model) as toDoModel">
      {{toDoModel.toDo}}
    </ng-container>
  </td>
</ng-container>

where:

assertItemType(item: ToDoInterface): ToDoInterface {
  return item;
}

works.

but not sure if it the best way to do it

like image 121
Lean Pilar Avatar answered Nov 04 '22 03:11

Lean Pilar


This can be solved by wrapping your variable inside another ng-template

The type assertion is noticed by the IDE when *ngFor or *ngIf is in use. This is somehow another workaround, but I liked a lot more than other solutions because it just adds 2 more lines of code in the HTML, of course if you're using your variable only 1 or 2 times this other solution is better. My answer:

Instead of this:

<ng-template *ngTemplateOutlet="foo; context: {$implicit: {fooProp: 'Hello!'}}"></p>
<ng-template #foo let-args>
    This is untyped: {{ args.fooProp }}<br>
</ng-template>

Do this:

<ng-template *ngTemplateOutlet="foo; context: {$implicit: {fooProp: 'Hello!'}}"></p>
<ng-template #foo let-untypedArgs>
    <ng-template [ngIf]="identity(untypedArgs)" let-args="ngIf">
        This is typed: {{ args.fooProp }}<br>
    </ng-template>
</ng-template>
identity(foo: Foo): Foo {
    return foo;
}

With this, now if you add an invalid property to your context, you'll get the following compilation error which is great, here's a stackblitz demo, The downside with this solution is that the inner <ng-template> is rendered later because of the [ngIf].

Property 'newFooProp' does not exist on type 'Foo'.

This is the same answer I gave at this other question.

like image 2
luiscla27 Avatar answered Nov 04 '22 02:11

luiscla27


Although the question is bit older I like to add a method that I used to achieve IDE type-hints.

First we can just add an additional method like,

  asRequest(request: any): Request{
    return workflow as Workflow;
  }

So, now you can wrap the request with that method.

<mat-cell *matCellDef="let request">
     <a [href]="asRequest(request).url" target="_blank">{{asRequest(request).requestId}}</a>
</mat-cell>

So the just request is now asRequest(request). (You can think like its a function for casting. Actually it is!)

I know this way makes some extra function calls, but it will do what you needed.

like image 1
Tharindu Sathischandra Avatar answered Nov 04 '22 02:11

Tharindu Sathischandra