Comments 13
Академический интерес)
Typescript дает это из коробки. Но подход интересный, кроме академического интереса, не вижу ничего более. Хотя интересно было узнать - юз кейс.
В каждом втором проекте встречается штука вроде Result<T>, у которого есть `T Result.Success` и `Error Result.Fail`. Вместо этого можно было бы объявлять сигнатуру метода, который отдает ровно один из указанных типов, вроде `(TResult Result | TError Error)`, без объявления вспомогательного типа-контейнера для каждого такого варианта (как в статье)
Лучшим способом реализовать Union Type было бы сделать монаду Either, а не встраивать это через ООП
Рекомендую ознакомиться с этой статьей, где описано, как устроена алгебра типов
https://bartoszmilewski.com/2015/01/13/simple-algebraic-data-types/
throw new ArgumentOutOfRangeException(nameof(worker), worker, null)
Ну вот это вот убивает весь смысл. В языках с полноценной поддержкой не нужно писать дефолт-ветку. И если мы добавляем новое значение в юнион, то код, делающий паттерн-матчинг, перестаёт компилироваться, вынуждая обработать новое значение. А у вас при добавлении нового значения всё радостно скомпилируется, но потом будет падать в рантайме.
P.S. Паттерн visitor позволяет более типобезопасно реализовать эмуляцию switch'а, без дефолт-веток.
Создаваемые свойства
Get/Set
Не set, а init, который хоть и set, но всё-же компилятор выдаст ошибку при попытке вызвать set.
Хотя F# даже метод такой не добавляет
Есть готовая библиотека, предоставляющая "почти" размеченные объединения:
Discriminated Unions в C#