Search code examples
angulartypescript

How using Angular 14 trackBy Function with strict-mode: true?


I have the problem to use trackBy in angular 14 with strict-mode: true,

This is the code (which works like charme in strict-mode: false)

app.component.html:

<div *ngFor="let item of items; index as i; trackBy: trackByFn">
  {{ i + 1 }} {{item.name}}
</div>


<br>

<button (click)="addSomething()">Load Data</button>

app.components.ts

import { Component } from '@angular/core';

interface DemoArray {
  id: number;
  name: string;
}

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  title = 'angular-sandbox';

  public items: DemoArray[] = [
    { id: 0, name: 'Apfel' },
    { id: 1, name: 'Mango' },
    { id: 2, name: 'Birne' },
  ];

  public addSomething(): void {
    this.items = [
      { id: 0, name: 'Apfel' },
      { id: 1, name: 'Mango' },
      { id: 2, name: 'Birne' },
      { id: 3, name: 'Kiwi' },
      { id: 4, name: 'Mandarine' },
      { id: 5, name: 'Banane' },
    ];
  }

  trackByFn(item) {
    return item.id;
  }
}

When using strict-mode:true and changing the trackByFn to:

  trackByFn(item: { id: any }) {
    return item.id;
  }

VSCode says:

Type '(item: { id: any; }) => any' is not assignable to type 'TrackByFunction'.ngtsc(2322) app.component.ts(8, 44): Error occurs in the template of component AppComponent.


Solution

  • Strict mode in Angular enables below things

    • Enables strict mode in TypeScript
    • Strict angular compiler strictTemplates, strictInjectionParameters, and strictInputAccessModifiers
    • Reduced bundle size budget

    Because strictTemplates types on templates are strictly checking its types, like how it does in typescript.

    Now in this case, trackBy we are passing TrackByFunction. Currently written trackByFn does not follow the type TrackByFunction.

    interface TrackByFunction<T> {
      <U extends T>(index: number, item: T & U): any
    }
    

    So the trackByFn function should follow the TrackByFunction interface signature.

    trackByFn(index: number, item: { id: any }) {
       return item.id;
    }