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 {