Frequently Asked Questions (FAQ)
This page answers some common questions you might have about JSOS.
General
Is JSOS free to use?
Yes. JSOS is free as in "free beer", and it's also open-source.
JSOS is licensed under the MIT-0 license, also called "MIT No Attribution License".
It is similar to the popular MIT License, but it has one crucial difference: You do not have to credit the creators of the library.
This license allows you to use JSOS in whatever way you see fit.
The MIT-0 license is comparable to releasing the code as public domain. However, many countries don't define what "public domain" means in legal terms, so a license is required to ensure the software can be used as if it was public domain.
JSOS is a very fundamental JavaScript library. You could even say that it transforms JavaScript into a different kind of language. That's why we want it to be used as freely as JavaScript itself, even though you don't write in JSOS, you write with JSOS.
Can I use JSOS with TypeScript?
Maybe. But we don't recommend using both in the same project. JSOS is primarily a JavaScript library. It is written by JavaScript developers, in JavaScript, for other JavaScript developers.
It might work with TypeScript projects, but we do not offer support for this usecase.
JSOS has its own type system, and that might somewhat clash with TypeScript's type system.
We also think there is not much benefit to using both, since JSOS offers many of the same benefits that TypeScript offers.
See our comparison of JSOS and TypeScript for how you would write code in JSOS versus in TypeScript.
Does JSOS work in the browser?
Yes. JSOS works in modern browsers that support ECMAScript 2020 and later. This is true for most current browsers, including Chrome, Safari, Edge, Firefox, Opera, Brave, LibreWolf.
Most of the advanced JS features used by JSOS have been available in the major browsers since at least 2021.
JSOS is implemented as ECMAScript modules. That means you can use it out of the box in the browser. However, you might want to build and use a bundle so that the browser has less requests to send to the server.
See Installing a Browser Bundle in the getting started guide.
Does JSOS work in Node.js?
Yes. JSOS works out of the box in Node.js. You can install it with NPM:
npm i @fed1/jsos
Does JSOS work in Deno, bun, ...?
Probably, yes. JSOS does not use any browser-specific or node-specific APIs. It should work in all ECMAScript 2020+ environments.
However, we currently only test the library in browsers and Node.js. We might test it in more environments if there's enough interest.
Why does JSOS not work in legacy browsers?
JSOS relies heavily on some modern JavaScript features that cannot be emulated using shims and similar techniques to port code to older ECMAScript versions.
These JS features include:
- Proxies
- WeakSet, WeakMap, WeakRef
This means that not even Babel can make JSOS work in Internet Explorer. However, JSOS should work in 95 percent of all browsers currently in use today (according to caniuse).
Multimethods
What is a multimethod?
A multimethod, also called a generic function, is a function that has more than one implementation. When a multimethod is called, an algorithm determines which of the implementations of the multimethod should be called.
These implementations are called methods, that's why a generic function is called a multimethod: it contains multiple methods.
What is a method?
In JavaScript, a method is just a function that is a property of an object.
When we talk about methods in JSOS, what we mean instead is one single implementation of a multimethod.
JSOS methods are free functions belonging to a multimethod, which is also a function, but a generic one.
How do I create a multimethod?
import { Generic } from "@fed1/jsos";
const { multi } = Generic; // 'multi' is a multimethod
How do I define a method?
import { def } from "@fed1/jsos";
import { multi } from "somePackageWithAMultimethod";
def(multi, [/* signature */], (/* parameters */) => { /* implementation */ });
The signature is an array with of zero or more comparators. A comparator can be a type, a class, or a value.
The parameters are variables containing the actual values given to the multimethod when it is called. The number of parameters should match the number of comparators in the signature, and the order corresponds to the order in the signature.
The multimethod algorithm ensures that the code in implementation is only called when the arguments given to the multimethod fulfill the criteria defined by the signature.
For example, if the signature asks for a JSString
for argument 1, you can be
sure that whenever your implementation is called, argument 1 will always
be of type string
.
What happens when a multimethod doesn't have a matching method?
If a multimethod does not have a matching method for the arguments given to it, it throws an error.
The error can give you some helpful pointers for what went wrong, including a list of methods registered for the multimethod.
Can I remove a method once it has been added?
Yes. To remove a method from a multimethod, you can use the undef() function.
Can methods have a variable number of arguments?
Yes. You can use JSOS's rest
symbol in a method signature as a catch-all
parameter:
import { rest } from "@fed1/jsos";
def(multi, [rest], (...args) => { /* ... */ });
Traits
What is a trait?
A trait in JSOS is a bundle of related multimethods. Types can implement such a trait by adding implementations for the multimethods required by a trait.
Traits can be used in multimethod signatures just like types can. This means that if you use a trait in a signature, you can be sure that any object your implementation receives can be used with all the multimethods that are part of the trait.
You can think of a trait as a class that only defines behavior but no data.
How can I define a trait?
import { Trait, Generic } from "@fed1/jsos";
const { multi } = Generic;
const { MyTrait } = Trait(
[multi, TAny]
);
This defines a trait MyTrait
that requires types who implement it to
specialize the multimethod multi
with one argument that can be a TAny
or
any child type of TAny
.
How can my type implement a trait?
MyType.implement(SomeTrait, [
def(SomeTrait.someMultimethod, [], () => {})
]);
Does my type have to implement all methods of a trait?
Yes. Traits do not have any optional methods. You either implement a trait fully or you don't implement it at all.
If you try to implement a trait partially, JSOS will throw an error.
Will my type automatically have trait X
when I implement multimethod Y
?
No. JSOS has a nominal type system, not a structural one. Implementing
a set of multimethods separately from a trait does not mean that your type is
recognized as implementing the trait. You have to explicitly call the
.implement()
method on the type.
However, you can supply your existing methods in the .implement()
call if
you saved a reference to the method (e.g. assign the return value of def()
to a variable).
Can traits implement traits?
Yes. Traits can be implemented by both types and other traits. Both types
and traits have an .implement()
JS method for this purpose.