Search code examples
angulartypescriptgenerics

How to expect a specific Typescript function template as an Angular component input


I have one Angular component which has the following input

@Input() filterColumnFunction?: FilterColumnFunction;

This function type ('template') is the following

export type FilterColumnFunction = <T>(columnFilters: { [key: string]: string }, items: T[]) => T[];

The given function to the component is

filterColumnFunction = (columnFilters: { [key: string]: string }, items: MyDto[]): MyDto[] => {
    return items.filter((item) => item.name === 'test');
};

but when I call the component with this function as input, I always get the following error

<my-component [filterColumnFunction]="filterColumnFunction"></my-component>

`Type '(columnFilters: { [key: string]: string }, items: MyDto[]) => MyDto[]' is not assignable to type 'FilterColumnFunction'

I don't understand why my function is not considered as the FilterColumnFunction type and what I can do to make this work ?


Solution

  • The location of the generic type<T> should be before the assignment of the type.

    export type FilterColumnFunction<T> = (
      columnFilters: { [key: string]: string },
      items: T[]
    ) => T[];
    

    Full Code:

    import { Component, Input } from '@angular/core';
    import { bootstrapApplication } from '@angular/platform-browser';
    import 'zone.js';
    
    export interface MyDto {
      name: string;
    }
    
    export type FilterColumnFunction<T> = (
      columnFilters: { [key: string]: string },
      items: T[]
    ) => T[];
    
    @Component({
      selector: 'app-child',
      standalone: true,
      template: ``,
    })
    export class Child {
      @Input() filterColumnFunction?: FilterColumnFunction<MyDto>;
    }
    
    @Component({
      selector: 'app-root',
      standalone: true,
      imports: [Child],
      template: `
        <app-child [filterColumnFunction]="filterColumnFunction"></app-child>
      `,
    })
    export class App {
      filterColumnFunction: FilterColumnFunction<MyDto> = (
        columnFilters: { [key: string]: string },
        items: MyDto[]
      ): MyDto[] => {
        return items.filter((item: MyDto) => item.name === 'test');
      };
    }
    
    bootstrapApplication(App);
    

    Stackblitz Demo