32 ms·
You should really check out how to do ADT's in TS. It's incredibly simple and intuituve thanks to the union and Singleton support. type Shape = Point | Cir
by dtech 9y ago
You should really check out how to do ADT's in TS. It's incredibly simple and intuituve thanks to the union and Singleton support.
type Shape = Point | Circle
interface Point {
type: "Point"
x: number
}
interface Circle {
type: "Circle"
center: number
}
let x: Shape = foo()
if(x.type == "Circle")
log(x.x) // Error
It's enterily generic and flows through the whole type system. It makes nullability trivial and `Option` superfluous, since `Option<T>` is an alias for `T | null`. If you check it for null once the type will immediately become `T` from then on.
Try something like this with Dotty's enums, it's super easy to hit the limits there.
- tytytytytytytyt 9y agoYou've already hit a limit when you're having to pepper your code with C style union type checks, imo.
- dtech 9y agoYou don't get it, you don't have to pepper the code. If you already have a `Circle` the check is unneeded. If you have done the check the type is constrained. You do exactly as much or less checks as you would do pattern matches on sealed traits in Scala, except that it works as you except in all instances, not just with sealed traits.
- tytytytytytytyt 9y ago> You don't get it, you don't have to pepper the code. If you already have a `Circle` the check is unneeded. That's not even what I was talking about...
- dragonwriter 9y ago“Option<T>” is not an alias for “T | null”, which is apparent when you try to puzzle out how to represent “Option<Option<T>>”.
- lomnakkus 9y agoIndeed, and this is exactly why union types are not a replacement for algebraic data types. (Not disagreeing, just making the point more explicit.)