Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/pfgray/ts-adt
Generate Algebraic Data Types and pattern matchers
https://github.com/pfgray/ts-adt
Last synced: 17 days ago
JSON representation
Generate Algebraic Data Types and pattern matchers
- Host: GitHub
- URL: https://github.com/pfgray/ts-adt
- Owner: pfgray
- License: mit
- Created: 2019-11-21T17:49:08.000Z (almost 5 years ago)
- Default Branch: master
- Last Pushed: 2023-03-05T17:18:05.000Z (over 1 year ago)
- Last Synced: 2024-10-14T16:12:02.009Z (29 days ago)
- Language: TypeScript
- Size: 302 KB
- Stars: 315
- Watchers: 6
- Forks: 13
- Open Issues: 13
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# ADTs for typescript
### Enables succinct ADT declaration.
In typescript, [Algebraic Data Types](https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html#discriminating-unions) are encoded using union types with a discriminator field.
Example:
```ts
import { ADT } from "ts-adt";type Option = ADT<{
some: { value: A };
none: {};
}>;
```This translates to:
```ts
type Option = { _type: "some"; value: A } | { _type: "none" };
``````ts
declare const userImage: Option;function getUserImage(): string {
if (userImage._type === "some") {
return userImage.value; // value is accessible here, since _type is 'some'
} else {
return "http://example.com/defaultImage";
}
}
```## Pattern matching
Pattern matching is a common usecase when dealing with ADTs. You'll often find yourself in a position where you need to default to certain values depending on what the underlying value is. For this reason, we've included a `match` and `matchI` function:
```ts
import { ADT, match, matchI } from "ts-adt";declare const userImage: Option;
const img = matchI(userImage)({
some: ({ value }) => value,
none: () => "http://example.com/defaultImage",
});const img = pipe(
userImage,
match({
some: ({ value }) => value,
none: () => "http://example.com/defaultImage",
})
);
```Both functions work the same way, but their arguments are ordered differently for better inference in different cases.
### Partial Matching
You can also use _partial matching_ if you don't need to match against all possible cases.
Consider if you have an ADT of the shape:
```ts
type Xor = ADT<{
nothing: {};
left: { value: A };
right: { value: A };
}>;declare const myXor: Xor;
```You can supply an "otherwise" function which gets invoked if the value doesn't match any of the supplied matchers. The otherwise function will be passed a value whose type is the types which _weren't_ matched.
```ts
declare const myXor: Xor;matchPI(promise)({ nothing: () => 0 }, (rest) => {
// rest inferred as {_type: 'left', value: number } | {_type: 'right', value: number }
return rest.value;
});
```## Custom Discriminant field
By default, `ADT` and the `match` functions use the `_type` field as the discriminant. You can build an ADT using a different discriminant field, along with matching `match` functions by using the utilities in `ts-adt/MakeMatch`:
```ts
import { MakeADT, makeMatchers } from "ts-adt/MakeADT";type Option = MakeADT<
"typ",
{
some: { value: A };
none: {};
}
>; // { typ: 'some', value: A } | { typ: 'none' }const [match, matchP, matchI, matchPI] = makeMatchers("typ");
```You can also use `makeMatchers` to build matchers for ADTs in other libraries:
```ts
import * as O from "fp-ts/Option";const [match, matchP, matchI, matchPI] = makeMatchers("_tag");
pipe(
O.fromNullable("value"),
match({
None: () => 0,
Some: (v) => v.value,
})
);
```