Angenommen, Sie haben eine for-in-Schleife und stellen plötzlich fest, dass Ihr Variablentyp ein String und kein String-Literal-Union-Typ ist. Sie erhalten also diesen hässlichen Fehler, wenn Sie Ihre App mit tsc kompilieren, und ärgerlicherweise schreit Ihre Lieblings-IDE höchstwahrscheinlich aus vollem Halse:
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ user: number; nice: number; sys: number; idle: number; irq: number; }'. No index signature with a parameter of type 'string' was found on type '{ user: number; nice: number; sys: number; idle: number; irq: number; }'.ts(7053)
[!NOTE]
Nur um Ihnen zu zeigen, wie es geht, verwende ich os.cpus. Dort versuche ich, cpu.times zu durchlaufen, was ein Objekt ist. Weitere Infos findest du hier.
Hier ist also der problematische Code:
import { cpus } from 'os'; const logicalCoresInfo = cpus(); for (const logicalCoreInfo of logicalCoresInfo) { let total = 0; for (const type in logicalCoreInfo.times) { total += logicalCoreInfo.times[type]; // Darn it, TS is upset! } }Nach dem Login kopieren
Also fangen wir an. Im ersten Teil müssen wir einen benutzerdefinierten Dienstprogrammtyp für uns selbst erstellen. So wird unser endgültiger Dienstprogrammtyp aussehen:
type NestedKeysOf<T, K extends PropertyKey> = T extends object ? { [TKey in keyof T]-?: | (TKey extends K ? keyof T[TKey] : never) | NestedKeysOf<T[TKey], K>; }[keyof T] : never;
Lassen Sie es uns aufschlüsseln:
[TKey in Tonart von T]-? ist ein „Mapped Type“, der hier besonders nützlich ist, da wir den Namen der Schlüssel innerhalb des an diesen Dienstprogrammtyp übergebenen Objekts nicht kennen. Hier übergeben Sie logicalCoreInfo an ihn oder ein anderes Objekt, dann durchläuft es die Schlüssel, um daraus einen neuen Typ zu erstellen.
Und -? Ist da, um die Optionalität zu entfernen, sodass wir einen String-Literal-Vereinigungstyp aller Schlüssel haben? Mit anderen Worten: { keyName?: string } wird als { keyName: string } behandelt.
(TKey erweitert K ? keyof T[TKey] : nie) Überprüfen Sie, ob der aktuelle Schlüssel in der Iteration mit dem übergebenen Schlüssel (K) übereinstimmt. Wenn ja, werden alle darin enthaltenen Schlüssel als String-Literal-Union-Typ extrahiert und gib es zurück. Ansonsten gibt es nichts zurück.
Wenn Schritt 3 dann kein Ergebnis erbracht hat, wird dieser Dienstprogrammtyp rekursiv auf T[Tkey] angewendet, sodass unsere Dienstprogrammfunktion auch bei verschachtelten Objekten funktioniert. Dies wird allgemein als „Rekursiver bedingter Typ“ bezeichnet.
Schließlich bitten wir darum, die Vereinigung aller vom zugeordneten Typ generierten Typen zu nehmen. Kurz gesagt, wir reduzieren die verschachtelte Struktur.
Jetzt ist es also an der Zeit, es zu verwenden:
interface Person { name: string; address: { street: string; city: string; }; } type KeysOfAddress = NestedKeysOf<Person, 'address'>; // "street" | "city" // Or in our original example: type CpuTimesKeys = NestedKeysOf<typeof logicalCoreInfo, 'times'>; // ... total += logicalCoreInfo.times[type as CpuTimesKeys]; // ...
Das obige ist der detaillierte Inhalt vonRekursive bedingte Typen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!