Typescript имеет союзы, поэтому перечислены избыточные?
С тех пор как TypeScript вводил типы союзов, мне интересно, есть ли причина объявлять тип перечисления. Рассмотрим следующее объявление типа перечисления:
enum X { A, B, C }
var x:X = X.A;
и подобное объявление типа объединения:
type X: "A" | "B" | "C"
var x:X = "A";
Если они в основном служат одной и той же цели, а профсоюзы более мощные и выразительные, то зачем нужны перечисления?
Ответы
Ответ 1
Насколько я вижу, они не являются избыточными, по той простой причине, что типы объединения являются просто концепцией времени компиляции, тогда как перечисления фактически переносятся и заканчиваются в результирующем javascript (образце).
Это позволяет вам делать некоторые вещи с перечислениями, которые в противном случае невозможны с типами объединения (например, перечисление возможных значений перечисления)
Ответ 2
Есть несколько причин, по которым вы можете использовать enum
Я вижу большие преимущества использования объединения в том, что они предоставляют краткий способ представления значения несколькими типами, и они очень удобочитаемы. let x: number | string
РЕДАКТИРОВАТЬ: Начиная с TypeScript 2.4 Enums теперь поддерживает строки.
enum Colors {
Red = "RED",
Green = "GREEN",
Blue = "BLUE",
}
Ответ 3
Перечисления могут концептуально рассматриваться как подмножество типов объединения, выделенных для значений типа int
и/или string
, с некоторыми дополнительными функциями, упомянутыми в других ответах, которые делают их удобными для использования.
Но перечисления не совсем безопасны:
enum Colors { Red, Green, Blue }
const c: Colors = 100; // No errors!
type Color =
| 0 | 'Red'
| 1 | 'Green'
| 2 | 'Blue';
const c2: Color = 100; // Error: Type '100' is not assignable to type 'Color'
Типы объединения поддерживают разнородные данные и структуры, включая полиморфизм, например:
class RGB {
constructor(
readonly r: number,
readonly g: number,
readonly b: number) { }
toHSL() {
return new HSL(0, 0, 0); // Fake formula
}
}
class HSL {
constructor(
readonly h: number,
readonly s: number,
readonly l: number) { }
lighten() {
return new HSL(this.h, this.s, this.l + 10);
}
}
function lightenColor(c: RGB | HSL) {
return (c instanceof RGB ? c.toHSL() : c).lighten();
}
Я склонен смотреть на F #, чтобы увидеть хорошие практики моделирования. Цитата из F # для удовольствия и прибыли, которая может быть полезна здесь:
В общем, вам следует отдавать предпочтение разграниченным типам объединений, а не перечислениям, если только вам не нужно иметь значение типа int
(или string
), связанное с ними.