Mit den neuesten Versionen von TypeScript ist es einfach, iterierbare Vereinigungstypen zu deklarieren. Daher sollten Sie Unionstypen Enums vorziehen.
So deklarieren Sie iterierbare Vereinigungstypen
const permissions = ['read', 'write', 'execute'] as const;
type Permission = typeof permissions[number];
for (const permission of permissions) {
}
Wenn sich die tatsächlichen Werte des Unionstyps nicht sehr gut beschreiben, können Sie sie wie bei Aufzählungen benennen.
enum Permission {
Read = 'r',
Write = 'w',
Execute = 'x'
}
const Permission = {
Read: 'r',
Write: 'w',
Execute: 'x'
} as const;
type Permission = typeof Permission[keyof typeof Permission];
for (const permission of Object.values(Permission)) {
}
Verpassen Sie nicht die as const
Behauptung, die in diesen Mustern die entscheidende Rolle spielt.
Warum ist es nicht gut, Aufzählungen zu verwenden?
1. Nicht konstante Aufzählungen passen nicht zum Konzept "eine typisierte Obermenge von JavaScript".
Ich denke, dieses Konzept ist einer der entscheidenden Gründe, warum TypeScript unter anderen altJS-Sprachen so beliebt geworden ist. Nicht konstante Enums verletzen das Konzept, indem sie zur Laufzeit lebende JavaScript-Objekte mit einer Syntax ausgeben, die nicht mit JavaScript kompatibel ist.
2. Konstanten haben einige Fallstricke
Konstanten können mit Babel nicht transpiliert werden
Derzeit gibt es zwei Problemumgehungen für dieses Problem: Sie müssen Konstanten manuell oder mit dem Plugin entfernen babel-plugin-const-enum
.
Das Deklarieren von Konstanten in einem Umgebungskontext kann problematisch sein
Umgebungskonstanten sind nicht zulässig, wenn das --isolatedModules
Flag bereitgestellt wird. Ein TypeScript-Teammitglied sagt, dass " const enum
in DT wirklich keinen Sinn ergibt" (DT bezieht sich auf DefinitelyTyped) und "Sie sollten stattdessen einen Union-Typ von Literalen (Zeichenfolge oder Zahl) verwenden" anstelle von Konstanten im Umgebungskontext.
Konstanten unter --isolatedModules
Flagge verhalten sich auch außerhalb eines Umgebungskontexts seltsam
Ich war überrascht, diesen Kommentar auf GitHub zu lesen und bestätigte, dass das Verhalten mit TypeScript 3.8.2 immer noch stimmt.
3. Numerische Aufzählungen sind nicht typsicher
Sie können numerischen Aufzählungen eine beliebige Nummer zuweisen.
enum ZeroOrOne {
Zero = 0,
One = 1
}
const zeroOrOne: ZeroOrOne = 2;
4. Die Deklaration von String-Aufzählungen kann redundant sein
Wir sehen manchmal diese Art von String-Aufzählungen:
enum Day {
Sunday = 'Sunday',
Monday = 'Monday',
Tuesday = 'Tuesday',
Wednesday = 'Wednesday',
Thursday = 'Thursday',
Friday = 'Friday',
Saturday = 'Saturday'
}
5. Das Muster der Vereinigungstypen ist viel cooler
Die Muster, die ich am Anfang dieser Antwort gezeigt habe, sind die großartigen Beispiele aus der Praxis, wie flexibel und ausdrucksstark TypeScript ist. Ich glaube, Sie können TypeScript besser verstehen und ein guter TypeScript-Programmierer sein, wenn Sie solche Muster aggressiv anwenden.
Ich muss zugeben, dass es eine Aufzählungsfunktion gibt, die von Gewerkschaftstypen nicht erreicht wird
Auch wenn aus dem Kontext ersichtlich ist, dass der Zeichenfolgenwert in der Aufzählung enthalten ist, können Sie ihn nicht der Aufzählung zuweisen.
enum StringEnum {
Foo = 'foo'
}
const foo1: StringEnum = StringEnum.Foo;
const foo2: StringEnum = 'foo';
Dies vereinheitlicht den Stil der Enum-Wertzuweisung im gesamten Code, indem die Verwendung von Zeichenfolgenwerten oder Zeichenfolgenliteralen vermieden wird. Dieses Verhalten stimmt nicht mit dem Verhalten des TypeScript-Typsystems an den anderen Stellen überein und ist etwas überraschend. Einige Leute, die dachten, dies sollte behoben werden, werfen Probleme auf ( dies und das ), in denen wiederholt erwähnt wird, dass die Absicht von String-Aufzählungen besteht um "undurchsichtige" Zeichenfolgentypen bereitzustellen: dh sie können geändert werden, ohne die Verbraucher zu ändern.
enum Weekend {
Saturday = 'Saturday',
Sunday = 'Sunday'
}
const weekend: Weekend = Weekend.Saturday;
Beachten Sie, dass diese "Undurchsichtigkeit" nicht perfekt ist, da die Zuweisung von Aufzählungswerten zu Zeichenfolgenliteraltypen nicht beschränkt ist.
enum Weekend {
Saturday = 'Saturday',
Sunday = 'Sunday'
}
const saturday: 'Saturday' = Weekend.Saturday;
Wenn Sie der Meinung sind, dass diese "undurchsichtige" Funktion so wertvoll ist, dass Sie alle oben beschriebenen Nachteile im Austausch dafür akzeptieren können, können Sie Zeichenfolgenaufzählungen nicht aufgeben.
So entfernen Sie Aufzählungen aus Ihrer Codebasis
Mit der no-restricted-syntax
Regel von ESLint, wie beschrieben .