
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
safe-types
Advanced tools
Type safe utils inspired from the Rust language for writing better JavaScript.
Type safe utils inspired from the Rust language for writing better JavaScript. Written in typescript with support for flow definitions.
Follow the link for method references. Below is an explanation of why and how.
This library started out as an experiment both to learn Rust concepts as well as to determine whether some of Rust's types can be mapped to TypeScript and improve the safety of TypeScript/JavaScript.
Side Note: It's my opinion that a library like this requires a 100% TypeScript environment to provide security around JS types. Without the TypeScript compiler and tooling, these primitives may make your data more opaque rather than provide insight and clarity into the many states application data can be in. Using an editor like vscode can provide some built in intellisense when running in JavaScript without TypeScript, but inference is limited.
The two main exports of this library are implementations of the Maybe Monad and the Either Monad. I wrote this library without any formal learning in category theory, so the Rust standard library was essential to guiding my implementation of these Monad patterns. While these functional programming concepts are notoriously arcane, they are much easier to learn in practice than in theory.
Imagine if you could rewrite JavaScript and remove null and undefined types.
The dreaded error undefined is not a function could be gone forever!. Sounds
great, right? But there are still many times when you need a way to represent
nothing. What happens if your function doesn't return anything? It turns out
that there is a pattern for doing with type safety.
The option type is a simple type that can exist in one of two states--having
some value, or having none (nothing). In a way, this is very similar
to having a value or having null. However, an option carries the context of
the type it represent regardless of it being present. Instead of calling a
function expecting a string or null, you receive an option of a string
Option<string>. That option may be Some<string>, or it may be
None. This is why it's known as the Maybe Monad.
So how does this work? We wrap the state of having a value in a box. In
JavaScript, this box is implemented with a plain old JavaScript object (POJO).
Let's imagine what a Some<string> would look like for the string
'typescript':
type Some<T> = { value: T };
let someString: Some<string> = { value: "typescript" };
This is fine for a simple box to hold our value, but how would we represent
None? What about an empty object?
type None = {};
let noneString: None = {};
Now we have a consistent object shape, so we need a way to distinguish the state
of the option type. We want to keep our option generic, so it can't be
implemented with any kind of value checking on the value property of the
Some object. Instead, we can use another property that will be common to both
states that we call a type discriminant.
type Some<T> = {
value: T;
state: "Some";
};
type None = {
state: "None";
};
This is enough for us to implement the option type! But keeping track of the option state is tedious, and the abstraction shouldn't allow us to know the internal state. That's where the library comes in.
Generally, usage of the option type starts by wrapping a value of which we know
the type, but we also know that it may return null or undefined. To do that,
we can use the Option.of or Option.from methods (one is just an alias).
function getAtIndex(index, list) {
return Option.of(list[index]);
}
let list = [1, 2, 3];
let firstElement = getAtIndex(0, list);
// Some<1>
let probablyNot = getAtIndex(10, list);
// None
Both Option.of and its alias only create a Some type if the value is not
null or undefined. From then on, you can make use of the methods available
on the Option type to perform operations safely. Let's try another example
like getting the input value from an HTMLInputElement.
// document.querySelector returns an element or null
let maybeInput = Option.of(document.querySelector("input[name=email]"));
// If we are certain this exists, we can unwrap the value.
// It will throw an error if the option is a `none`
let input = maybeInput.unwrap();
// We can also have it throw a custom error message
input = maybeInput.expect("expected an input element with name=email");
// We can safely read a value if we provide a default
let value = maybeInput.map_or("", element => element.value);
// We can even do a chain of dependent actions without dealing with null!
let maybeSubmitBtn = maybeInput.and_then(element =>
Option.of(element.parent.querySelector("button[type=submit]"))
);
You can browse the set of methods known as combinators, but the most important
method is match. The match method accepts an object with methods for each
possible state of the option (Some and None) and must return the same type
for each possibility.
let luckyNumber = Option.of(list.find(num => num > 100)).match({
// Called with the value.
Some(num) {
return num;
},
None() {
return 0;
},
});
The Task object is similar to RxJS observables, and can be converted in just a few lines of code.
const fetchTask = new Task(async ({ Ok, Err }) => {
try {
const response = await fetch("https://example.test/some/url");
const data = await response.json();
return Ok(data);
} catch (error) {
return Err(error);
}
});
const fetchStream = new Observable(async subscriber => {
await fetchTask.fork({
Ok: data => subscriber.next(data),
Err: error => subscriber.error(error),
});
subscriber.complete();
});
It is important to note that while the Task model maps nicely to Observables, it is missing the mechanisms to cancel its work. For this reason, there is no teardown function returned from the subscribe function passed to the Observable's constructor.
The lack of cancellation gets at the key differences between Tasks and Observables.
FAQs
Type safe utils inspired from the Rust language for writing better JavaScript.
The npm package safe-types receives a total of 264 weekly downloads. As such, safe-types popularity was classified as not popular.
We found that safe-types demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.