Я обожаю 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 typefunction 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