Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/akhansari/ts-adt

Algebraic Data Types & Typescript
https://github.com/akhansari/ts-adt

adt algebraic-data-types typescript

Last synced: 2 months ago
JSON representation

Algebraic Data Types & Typescript

Awesome Lists containing this project

README

        

# Algebraic Data Types & Typescript

Algebraic data types are a way of representing data by **combining** simple types using algebraic operations.
There are two main kinds of algebraic types: product types and sum types. Discriminated unions are a specific implementation of sum types.

## Product types (AND types)

Product types represent a combination of types.

```typescript
type Shirt = {
size: string
sleeveLength: string
shape: string
}
```

## Sum types (OR types)

Sum types represent a choice between types.

```typescript
type ShirtSize = "S" | "M" | "L" | "XL" | "XXL"
type SleeveLength = "Short" | "Long"
```

## Compose

Compose small types from other small types.

```typescript
type SleeveLength = "Short" | "Long"

type Shirt = {
size: "S" | "M" | "L" | "XL" | "XXL"
sleeveLength: SleeveLength
shape: string
}
```

## Pattern Matching

It's possible by adding a "kind" field to the product type.

```typescript
type SleeveLength = "Short" | "Long"

type Shirt = {
kind: "Shirt"
size: "S" | "M" | "L" | "XL" | "XXL"
sleeveLength: SleeveLength
shape: string
}

type Jean = {
kind: "Jean"
hipSize: number
legSize: number
...
}

type Clothing = Shirt | Jean

const clothing: Clothing = {
kind: "Shirt",
size: "L",
sleeveLength: "Short",
shape: "Straight",
}

const describeClothing = (clothing: Clothing) => {
switch (clothing.kind) {
case "Shirt": return "This is a shirt!"
case "Jean": return "This is a jean!"
}
}
```

You can go further by adding sections to kinds in order to combine Clothing and Shoes.

- `kind: "Clothing/Shirt"`
- `kind: "Clothing/Jean"`
- `kind: "Shoes/Sneakers"`
- `kind: "Shoes/Boots"`

```typescript
type Product = {
id: number
price: Price
item: Clothing | Shoes
}
```

## OpenAPI

In OpenAPI specification, sum types are represented by `oneOf`.

```yaml
Clothing:
oneOf:
- $ref: "#/components/schemas/Shirt"
- $ref: "#/components/schemas/Jean"
discriminator:
propertyName: kind
mapping:
Shirt: "#/components/schemas/Shirt"
Jean: "#/components/schemas/Jean"
```