feat(fp): WP-06 — kill $any() in templates (18x)
Make AsyncLoadedDirective generic with a static ngTemplateContextGuard for AsyncComponent's own internal typing. That can't propagate to consumer `<ng-template appAsyncLoaded let-p>` sites though -- Angular only infers a structural directive's type parameter from an input bound on that same node, not from a sibling input on the parent component -- so the ~9 root-cause consumers (dashboard, registration-detail, aanvraag-detail, registratie-wizard) instead unwrap the RemoteData Success value via a typed computed() and narrow it locally with `@if (x(); as p)`. The remaining union-narrowing casts (registration-summary, showcase concepts page) are replaced with a stable @let binding and a direct resource read, respectively. Documented as a deviation in WP-06's backlog file.
This commit is contained in:
@@ -6,10 +6,20 @@ import { AlertComponent } from '@shared/ui/alert/alert.component';
|
||||
import { ButtonComponent } from '@shared/ui/button/button.component';
|
||||
import { RemoteData, fromResource, foldRemote } from '@shared/application/remote-data';
|
||||
|
||||
/* Slot markers. Put on <ng-template> children of <app-async>. */
|
||||
/* Slot markers. Put on <ng-template> children of <app-async>. Generic so the
|
||||
$implicit context is typed as the resource's T instead of unknown — see
|
||||
AsyncComponent's contentChild<AsyncLoadedDirective<T>> below, which threads the
|
||||
host's own T through the query result type. */
|
||||
@Directive({ selector: '[appAsyncLoaded]' })
|
||||
export class AsyncLoadedDirective {
|
||||
constructor(public tpl: TemplateRef<{ $implicit: unknown }>) {}
|
||||
export class AsyncLoadedDirective<T = unknown> {
|
||||
constructor(public tpl: TemplateRef<{ $implicit: T }>) {}
|
||||
|
||||
static ngTemplateContextGuard<T>(
|
||||
_dir: AsyncLoadedDirective<T>,
|
||||
_ctx: unknown,
|
||||
): _ctx is { $implicit: T } {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@Directive({ selector: '[appAsyncLoading]' })
|
||||
export class AsyncLoadingDirective {
|
||||
@@ -88,7 +98,7 @@ export class AsyncComponent<T> {
|
||||
retryText = input($localize`:@@async.retry:Opnieuw proberen`);
|
||||
emptyText = input($localize`:@@async.empty:Geen gegevens gevonden.`);
|
||||
|
||||
loadedTpl = contentChild.required(AsyncLoadedDirective);
|
||||
loadedTpl = contentChild.required<AsyncLoadedDirective<T>>(AsyncLoadedDirective);
|
||||
loadingTpl = contentChild(AsyncLoadingDirective);
|
||||
emptyTpl = contentChild(AsyncEmptyDirective);
|
||||
errorTpl = contentChild(AsyncErrorDirective);
|
||||
|
||||
Reference in New Issue
Block a user