javascript / expert
Snippet
Tiefen-unveränderliche Tupel-Typumwandlung für Angular Signal-Selektoren
Rekursive bedingte Mapped Types in TypeScript wandeln komplexe Zustands-Interfaces und Tupel-Datentypen in tiefen-unveränderliche Strukturen um. In Angular Computed Signals garantiert diese Typ-Transformation zur Kompilierzeit, dass verschachtelte Zustände nicht direkt mutiert werden können.
snippet.js
javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
export type DeepReadonly<T> = T extends (...args: any[]) => any? T: T extends ReadonlyArray<infer U>? ReadonlyArray<DeepReadonly<U>>: T extends object? { readonly [K in keyof T]: DeepReadonly<T[K]> }: T;import { Component, signal, computed } from '@angular/core';interface AppState {userPermissions: [string, ...string[]];metadata: { config: { activeTheme: string } };}@Component({selector: 'app-state-viewer',standalone: true,template: `<div>Theme: {{ readonlyState().metadata.config.activeTheme }}</div>`})export class StateViewerComponent {private rawState = signal<AppState>({userPermissions: ['READ', 'WRITE', 'EXECUTE'],metadata: { config: { activeTheme: 'dark' } }});readonlyState = computed<DeepReadonly<AppState>>(() =>Object.freeze(this.rawState()) as DeepReadonly<AppState>);attemptMutation(): void {const state = this.readonlyState();// TS Compiler Error: Cannot assign to 'activeTheme' because it is a read-only property// state.metadata.config.activeTheme = 'light';}}
angular
Erklärung
1
export type DeepReadonly<T> = T extends (...args: any[]) => any ? T ...
Definiert einen rekursiven bedingten generischen Typen, der das readonly-Attribut auf alle verschachtelten Eigenschaften, Arrays und Tupel anwendet.
2
userPermissions: [string, ...string[]];
Deklariert einen nicht-leeren Tupel-Datentyp, der mindestens ein anfängliches String-Element erfordert.
3
readonlyState = computed<DeepReadonly<AppState>>(() => ...
Erstellt ein Angular Computed Signal, das den Zustand strikt verpackt im DeepReadonly-Typen wiedergibt.
4
// state.metadata.config.activeTheme = 'light';
Demonstriert die Verhinderung verschachtelter Objektmutationen zur Kompilierzeit durch den Mapped Type.