Get Readonly Keys
Challenge
Implement a generic GetReadonlyKeys<T> that returns a union of the readonly keys of an Object.
For example
interface Todo {
readonly title: string;
readonly description: string;
completed: boolean;
}
type Keys = GetReadonlyKeys<Todo>; // expected to be "title" | "description"
Solution
Zur Lösung dieses Problems definieren wir einen Hilfstyp IsReadOnly, der ein Objekttyp sowie einen Schlüssel des Objekttyps entgegennimmt und angibt, ob der Schlüssel readonly ist. Hierfür wird der Wert mittels Pick aus dem Objekttyp extrahiert und mit einem mapped type verglichen, welcher das gleiche Schlüssel / Wert Paar aufweist. Ist der Schlüssel also im originalen Objekttyp nicht readonly, so ist das Ergebnis nicht gleich, und damit der Schlüssel nicht readonly.
// Equal<{foo: bar}, {readonly foo: bar}> => false
// Equal<{readonly foo: bar}, {readonly foo: bar}> => true
type IsReadOnly<T, P extends keyof T> = Equal<
Pick<T, P>,
{ readonly [K in P]: T[P] }
>;
Der finale Typ stellt einen mapped type dar, bei dem wir bereits in der Iteration über die Schlüssel prüfen, ob der Schlüssel readonly ist. Indem wir zu Beginn des mapped typ noch ein keyof ergänzen, erhalten wir alle readonly-Schlüssel als Vereinigung:
type GetReadonlyKeys<T> = keyof {
[Key in keyof T as IsReadOnly<T, Key> extends true ? Key : never]: T[Key];
};