@practical-fp/union-types
v1.5.1
Published
A Typescript library for creating discriminating union types.
Downloads
14,061
Maintainers
Readme
Union Types
A Typescript library for creating discriminating union types. Requires Typescript 4.2 or higher.
Typescript Handbook on discriminating union types
Example
import { impl, Variant, match } from "@practical-fp/union-types"
type Shape =
| Variant<"Circle", { radius: number }>
| Variant<"Square", { sideLength: number }>
const { Circle, Square } = impl<Shape>()
function getArea(shape: Shape) {
return match(shape)
.with(Circle, ({ radius }) => Math.PI * radius ** 2)
.with(Square, ({ sideLength }) => sideLength ** 2)
.done()
}
const circle = Circle({ radius: 5 })
const area = getArea(circle)
Installation
$ npm install @practical-fp/union-types
Usage
Defining a discriminating union type
import { Variant } from "@practical-fp/union-types"
type Shape =
| Variant<"Circle", { radius: number }>
| Variant<"Square", { sideLength: number }>
This is equivalent to the following type:
type Shape =
| { type: "Circle", value: { radius: number } }
| { type: "Square", value: { sideLength: number } }
Creating an implementation
import { impl } from "@practical-fp/union-types"
const { Circle, Square } = impl<Shape>()
impl<>()
can only be used if your environment has full support
for Proxies.
Circle.is
and Square.is
can be used to check if a shape is a circle or a square.
They also act as type guards.
const shapes: Shape[] = [circle, square]
const sideLengths = shapes.filter(Square.is).map(square => square.value.sideLength)
Generics
impl<>()
also supports generic union types.
In case the variant type uses unconstrained generics,
unknown
needs to be passed as its type arguments.
import { impl, Variant } from "@practical-fp/union-types"
type Result<T, E> =
| Variant<"Ok", T>
| Variant<"Err", E>
const { Ok, Err } = impl<Result<unknown, unknown>>()
In case the variant type uses constrained generics, the constraint type needs to be passed as its type arguments.
import { impl, Variant } from "@practical-fp/union-types"
type Result<T extends object, E> =
| Variant<"Ok", T>
| Variant<"Err", E>
const { Ok, Err } = impl<Result<object, unknown>>()