Я обожаю Union Type, потому что они дают невероятно удобный способ избавляться от интерфейсов, а также ООП Наследования и Полиморфизма, засчет появления Pattern Matching:
type UnactivatedUser = { email: string; password: null; activated: false; }
type ActivatedUser = { email: string; password: string; activated: true; }
type User = UnactivatedUser | ActivatedUser // вот это union type
function someFn(user: User) {
switch(typeof user) { // это Pattern Matching
case UnactivatedUser:
throw new Error("User must be activated")
case ActivatedUser:
return true
default:
safeGuard(user) // если мы добавим еще один тип к User, то вот здесь при компиляции будет ошибка, что мы не добавили на него еще один case
}
}
С некоторыми модификациями такой псевдокод можно реализовать на TS, Rust и Haskell.
А вот в Go такого нет... и именно поэтому приходится в огромном кол-ве мест использовать interface и мудрить какую-то универсальную логику, вместо того, чтобы на месте проверить тип и сделать то, что нам нужно
Union Type и Pattern Matching настолько полезные техники, что я сделал их
частью ФОП, поскольку они также дают доступ к Algebraic Data Types
–
https://fop.davidshekunts.ru/#d04ae9b9e8e24f3ab46144f1e8816fc2–
https://itnext.io/practical-introduction-to-algebraic-datatypes-adts-in-typescript-1cb6952e4c6d–
https://wiki.haskell.org/OOP_vs_type_classes–
https://doc.rust-lang.org/book/ch18-03-pattern-syntax.html