From 1a3bc3aa1dc46ecbec61aa7b2f4f8f1170660f7a Mon Sep 17 00:00:00 2001 From: Alexander Brandon Coles Date: Thu, 4 Jun 2026 17:08:18 +0200 Subject: [PATCH] Type InjectField token as ProviderToken Replaces the `any`-typed token parameter with `ProviderToken`, so a non-token argument is now a compile error and `defaultValue`/getter share that `T`. Runtime is unchanged. A property decorator cannot see the field type, so a token/field mismatch is still uncatchable here; `inject()` remains the safer option for DI-constructed classes. --- .../helpers/angular/inject-field.decorator.ts | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/frontend/src/app/shared/helpers/angular/inject-field.decorator.ts b/frontend/src/app/shared/helpers/angular/inject-field.decorator.ts index 3a852849d0d..e0776095bbb 100644 --- a/frontend/src/app/shared/helpers/angular/inject-field.decorator.ts +++ b/frontend/src/app/shared/helpers/angular/inject-field.decorator.ts @@ -1,24 +1,27 @@ import 'reflect-metadata'; -import { InjectOptions, Injector } from '@angular/core'; +import { InjectOptions, Injector, ProviderToken } from '@angular/core'; import { debugLog } from 'core-app/shared/helpers/debug_output'; export interface InjectableClass { injector:Injector; } -export function InjectField(token?:any, defaultValue:any = null, options?:InjectOptions) { - return (target:InjectableClass, property:string) => { - // eslint-ignore-next-line no-param-reassign - if (delete (target as any)[property]) { +export function InjectField( + token?:ProviderToken, + defaultValue:T | null = null, + options?:InjectOptions, +) { + return (target:InjectableClass, property:string):void => { + if (delete (target as unknown as Record)[property]) { Object.defineProperty(target, property, { - get(this:InjectableClass) { - if (token) { - return this.injector.get(token, defaultValue, options); - } - const type = Reflect.getMetadata('design:type', target, property); - return this.injector.get(type, defaultValue, options); + get(this:InjectableClass):T | null { + // When no token is given, fall back to the property's reflected + // design type (requires emitDecoratorMetadata). + const resolvedToken = (token + ?? Reflect.getMetadata('design:type', target, property)) as ProviderToken; + return this.injector.get(resolvedToken, defaultValue, options); }, - set(this:InjectableClass) { + set(this:InjectableClass):void { debugLog(`Trying to set InjectField property ${property}`); }, });