https://github.com/onegen-dev/optional.ts
TypeScript ‘Optional’ utility wrapper based on C++ ‘std::optional’
https://github.com/onegen-dev/optional.ts
cpp typescript utility utility-classes wrapper
Last synced: 3 months ago
JSON representation
TypeScript ‘Optional’ utility wrapper based on C++ ‘std::optional’
- Host: GitHub
- URL: https://github.com/onegen-dev/optional.ts
- Owner: onegen-dev
- License: mit
- Created: 2024-09-05T19:11:25.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2024-10-29T14:18:00.000Z (over 1 year ago)
- Last Synced: 2025-11-14T06:21:54.616Z (7 months ago)
- Topics: cpp, typescript, utility, utility-classes, wrapper
- Language: TypeScript
- Homepage:
- Size: 138 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# @onegen/optional
[

](https://www.npmjs.com/package/@onegen/optional)
`Optional` utility class in TypeScript, based on C++
[`std::optional`](https://en.cppreference.com/w/cpp/utility/optional).
Made as minimally as I could, without any dependencies. \
I just like how `std::optional` works and wanted it in JS/TS. \
Guess it’s mostly done unless I find some mistake or something. 🤷🏼♂️
```ts
import { Optional } from "@onegen/optional";
function saferDiv (x: number, y: number): Optional {
if (y === 0) return Optional.nullopt;
return Optional.some(x / y);
}
var result = saferDiv(2, 0);
if (!result.hasValue())
console.log('Dividing by zero again, you dummy?');
else
console.log('It’s ', result.value(), '!');
```
`Optional` is a wrapper helper class around a value that may or may not
be defined. Instead of returning some arbitrary value (like -1),
`null` or throwing an error, `Optional` can be returned, prompting you
– the dev – to first check if there is any value before actually using it
in a fun and type safe manner! \
Look, it’s not for everyone, but I like it.
## Working with `Optional`s
### Declaring
```typescript
import { Optional, some } from '@onegen/optional';
var opt1 = new Optional(2024);
var opt2 = Optional.some(2024);
var opt3 = some(2024)
```
All of these lines are equivalent. They create an `Optional` holding a number
value 2024. First line specifies the type explicitly, second implies it from
its value, third line is just a shorthand for the second.
As you – a smart TypeScript developer – might’ve guessed, you can’t change the
`Optional` type. Once you make an instance of `Optional`, the variable will
only ever have `Optional`.
```typescript
var opt = Optional.some(2024);
opt = Optional.some('2024'); // TS won’t let you do this!
```
While you can’t change the type, you can, of course, change the value:
```typescript
opt.assign(2026); // with a method, or
opt = Optional.some(2025); // by re-assigning
```
…and even remove it:
```typescript
opt.reset(); // with a method, or
opt = Optional.none(); // by re-assigning
opt = Optional.nullopt; // equivalent to Optional.none()
```
Do mind that this doesn’t clear the variable type. The variable is still
`Optional`, even if `nullopt`. It will ever contain only a number
or nothing.
### Typeless declaration
Be mindful when creating empty `Optional`s:
```typescript
var opt = Optional.none()
```
The type of `opt` is `Optional` and that is not something you really
want now. I wish I could somehow forbid this. Seriously, don’t do this.
When making an empty `Optional`, specify its type explicitly, for your
own sake:
```typescript
var opt: Optional = Optional.none();
var opt = new Optional();
```
### Base usage
The main advantage of `Optional` is that you don’t need an arbitrary
"did not work" value (-1) or use `null`s that you may forgot to check for.
`Optional` makes it natural (at least for me) to check if it has a value
before actually using it:
```typescript
const result: Optional = saferDivide(10, 0);
if (!result.hasValue())
return "Whoops, something went wrong!"
const value = result.value();
```
Calling `result.value()` while there is no value will lead to an error.
This little utility is not attempting to be Rust `Result`. If you want a more
robust error-handling utility, you might want to take a look at
[neverthrow](https://github.com/supermacro/neverthrow).
Fully recommend (not sponsored).
### Functions
#### Observers
| Function | Return Type | Description |
| :-----------------------------------: | :-------: | :------------------------------------------------------------------------------: |
| `Optional.hasValue()` | `boolean` | Checks whether the object contains a value |
| `Optional.value()` | `T` | Returns the included value (throws error if there is none) |
| `Optional.valueOr(defaultValue: T)` | `T` | Returns either the included value OR provided default value |
#### Modifiers
| Function | Return Type | Description |
| :-----------------------------------: | :-------: | :------------------------------------------------------------------------------: |
| `Optional.reset()` | `this` | Removes the contained value |
| `Optional.assign()` | `this` | Assigns a new contained value |
| `Optional.swap(other: Optional)` | `this` | Swaps values of same-type Optionals |
C++ also has [`emplace()`](https://en.cppreference.com/w/cpp/utility/optional/emplace),
but TS types cannot be used to make new instances, as far as I know.
`assign()` is also deviance from `std::optional`, but I chose to add it, as TS/JS
does not allow operator overloading.
Also, all modifier methods return themselves (`this`) to allow chaining.
```ts
var opt = Optional.some(2024);
opt.reset().assign(2025).reset();
```
#### Monadic Operations
| Function | Return Type | Description |
| :-----------------------------------: | :-------: | :------------------------------------------------------------------------------: |
| `Optional.andThen (fn: (value: T) => Optional)` | `Optional` | – |
| `Optional.transform (fn: (value: T) => U)` | `Optional` | – |
| `Optional.orElse (fn: () => Optional)` | `Optional` | – |
These are harder to explain in short Markdown table, there are simple usage examples
in [`optional-mon.test.ts`](test/optional-mon.test.ts). Who am I even writing this for
nobody will use this except me lmao.
## Licence

**@onegen/optional** is available as an open-source utility library licenced
under the [MIT Licence](https://en.wikipedia.org/wiki/MIT_License).
- TL;DR;NAL:
Do absolutely whatever you want with the code, just include
the LICENCE file if you re-distribute it.
- See [`LICENCE`](LICENCE) file or
[tl;drLegal](https://www.tldrlegal.com/license/mit-license)
for more details.