Closed anilanar closed 2 years ago
I see why nominal types are useful.
To elaborate on my second point, I personally would use a pattern like this.
import { impl, Variant } from "@practical-fp/union-types"
declare const SHAPE: unique symbol
type Circle = { radius: number } & typeof SHAPE
type Square = { sideLength: number } & typeof SHAPE
type Shape =
| Variant<"Circle", Circle>
| Variant<"Square", Square>
const { Circle, Square } = impl<Shape>()
function parseShape(shape: { radius?: number, sideLength?: number }) {
const { radius, sideLength } = shape
if (radius !== undefined && sideLength === undefined) {
return Circle({radius} as Circle)
} else if (radius === undefined && sideLength !== undefined) {
return Square({sideLength} as Square)
} else {
return undefined
}
}
Alright thanks.
Just dropping a note here, that it's possible to have nominal types by using a phantom property
readonly [someSymbol]: unique symbol
and then type-casting intag
function when creating a variant.i.e.
That way, the only way to construct a variant would be through the constructors returned by
impl
and it wouldn't even use symbols at runtime.It could be a different function called
nominalImpl
or it could be afunction impl(nominal: boolean)
, with all relevant types getting an additional generic argument<Nominal = false>
.Not use if type nominal types is interesting for others too or not.