diff --git a/apps/angular/10-utility-wrapper-pipe/src/app/app.component.ts b/apps/angular/10-utility-wrapper-pipe/src/app/app.component.ts index 9a8156a5f..aaf1434fb 100644 --- a/apps/angular/10-utility-wrapper-pipe/src/app/app.component.ts +++ b/apps/angular/10-utility-wrapper-pipe/src/app/app.component.ts @@ -1,20 +1,29 @@ import { Component } from '@angular/core'; +import { PersonUtilFunctionPipe } from './person-utils.pipe'; import { PersonUtils } from './person.utils'; @Component({ selector: 'app-root', + imports: [PersonUtilFunctionPipe], template: ` @for (activity of activities; track activity.name) { - {{ activity.name }} : - @for ( - person of persons; - track person.name; - let index = $index; - let isFirst = $first - ) { - {{ showName(person.name, index) }} - {{ isAllowed(person.age, isFirst, activity.minimumAge) }} - } +
+ {{ activity.name }} : + @for ( + person of persons; + track person.name; + let index = $index; + let isFirst = $first + ) { +
+ {{ person.name | personUtil: 'showName' : index }} + {{ + person.age + | personUtil: 'isAllowed' : isFirst : activity.minimumAge + }} +
+ } +
} `, }) diff --git a/apps/angular/10-utility-wrapper-pipe/src/app/person-utils.pipe.ts b/apps/angular/10-utility-wrapper-pipe/src/app/person-utils.pipe.ts new file mode 100644 index 000000000..1a045ead3 --- /dev/null +++ b/apps/angular/10-utility-wrapper-pipe/src/app/person-utils.pipe.ts @@ -0,0 +1,34 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +import { PersonUtils } from './person.utils'; + +type PersonUtilFunctionName = keyof typeof PersonUtils; + +type PersonUtilFunctionParams = Parameters< + (typeof PersonUtils)[T] +>; + +type FirstParam = T extends [infer First, ...unknown[]] ? First : never; + +type RestParams = T extends [unknown, ...infer Rest] ? Rest : never; + +@Pipe({ + name: 'personUtil', +}) +export class PersonUtilFunctionPipe implements PipeTransform { + transform( + value: FirstParam>, + functionName: T, + ...args: RestParams> + ): ReturnType<(typeof PersonUtils)[T]> { + /* + TODO: This is a bit of a hack to call the correct function + from PersonUtils based on the functionName argument. + We need to assert that the function exists and is callable, + but we also want to maintain type safety as much as possible. + The type assertions here are necessary to satisfy TypeScript's type system, + but they should be safe as long as the functionName argument is valid. + */ + return (PersonUtils[functionName] as Function)(value, ...args); + } +} diff --git a/apps/angular/10-utility-wrapper-pipe/src/app/person.utils.ts b/apps/angular/10-utility-wrapper-pipe/src/app/person.utils.ts index 66451dad4..2283f8ae5 100644 --- a/apps/angular/10-utility-wrapper-pipe/src/app/person.utils.ts +++ b/apps/angular/10-utility-wrapper-pipe/src/app/person.utils.ts @@ -1,9 +1,13 @@ -const showName = (name: string, index: number) => { +const showName = (name: string, index: number): string => { // very heavy computation return `${name} - ${index}`; }; -const isAllowed = (age: number, isFirst: boolean, activityAge: number) => { +const isAllowed = ( + age: number, + isFirst: boolean, + activityAge: number, +): string => { if (isFirst) { return 'always allowed'; } else {