Es ist möglich, einen DeepReadonly
Typ wie diesen zu erstellen:
type DeepReadonly<T> = {
readonly [P in keyof T]: DeepReadonly<T[P]>;
};
interface A {
B: { C: number; };
D: { E: number; }[];
}
const myDeepReadonlyObject: DeepReadonly<A> = {
B: { C: 1 },
D: [ { E: 2 } ],
}
myDeepReadonlyObject.B = { C: 2 }; // error:)
myDeepReadonlyObject.B.C = 2; // error:)
Das ist toll. Sowohl B
als B.C
auch sind schreibgeschützt. Wenn ich jedoch versuche zu ändern D
...
// I'd like this to be an error
myDeepReadonlyObject.D[0] = { E: 3 }; // no error:(
Wie soll ich schreiben DeepReadonly
, damit verschachtelte Arrays auch schreibgeschützt sind?
Lösung des Problems
Ab TypeScript 2.8 ist dies nun möglich und tatsächlich ein Beispiel in der PR für Conditional Types: https://github.com/Microsoft/TypeScript/pull/21316
Siehe auch die Hinweise zum Typrückschluss für bedingte Typen:
https://github.com/Microsoft/TypeScript/pull/21496
Ich habe das Beispiel leicht modifiziert, um den Typrückschluss für den schreibgeschützten Array-Werttyp zu verwenden, weil ich (infer R)[]
klarer finde, als Array<T[number]>
aber beide Syntaxen funktionieren. Ich habe auch das Beispielbit entfernt NonFunctionPropertyNames
, da ich Funktionen in meiner Ausgabe beibehalten möchte.
type DeepReadonly<T> =
T extends (infer R)[]? DeepReadonlyArray<R>:
T extends Function? T:
T extends object? DeepReadonlyObject<T>:
T;
interface DeepReadonlyArray<T> extends ReadonlyArray<DeepReadonly<T>> {}
type DeepReadonlyObject<T> = {
readonly [P in keyof T]: DeepReadonly<T[P]>;
};
Wenn Sie DeepReadonly auf diese Weise ausführen, bleiben auch optionale Felder erhalten (danke an Mariusz für die Information), z. B.:
interface A {
x?: number;
y: number;
}
type RA = DeepReadonly<A>;
// RA is effectively typed as such:
interface RA {
readonly x?: number;
readonly y: number;
}
Während TS in bestimmten Szenarien immer noch einige einfache Möglichkeiten bietet, die „Schreibgeschütztheit" zu verlieren, kommt dies einem const
Wert im C/C++-Stil so nahe, wie Sie es bekommen werden.
Keine Kommentare:
Kommentar veröffentlichen