Show HN: minfern – Type inference for JavaScript without transpilation
_sinelaw_ Sunday, December 28, 2025I wrote a type checker (minfern - https://github.com/sinelaw/minfern) for a subset of javascript with no transpilation. It accepts valid JS as input and allows a subset of JS code to pass the checking. There’s no transpilation or compilation needed. The input code can be run directly.
Try it online at: https://sinelaw.github.io/minfern/
It could be used for checking code targeting normal JS runtimes, or runtimes like mquickjs (though minfern is more strict but also allows things like ‘const’ which mquickjs doesn’t). minfern is based on the type system for Infernu, which I wrote back in 2015, but is less hacky and has a cleaner implementation.
Very simple example:
function calculateTotal(product, quantity) {
return product.price * quantity;
}
var item = {
name: "Wireless Mouse",
cost: 25 // Note the property name is 'cost', not 'price'
};
console.log(calculateTotal(item, 2));
Output: Error: Property 'price' not found in type {cost: Number, name: String}
╭─[ tests/example_error.js:11:13 ]
│
11 │ console.log(calculateTotal(item, 2));
│ ───────────┬───────────
│ ╰───────────── Property 'price' not found in type {cost: Number, name: String}
────╯
Type system features:- Full type inference with principle typing, support for type annotations
- Parameteric polymorphism (aka “generic functions”)
- Structural typing with row-type polymorphism
- Object method typing with equi-recursive types (for self/“this”)
- Polymorphic object methods (still considered rank-1)
- Basic constraints “Plus a” and “Indexable a” to allow + and [] to apply to different types like numbers, strings, arrays.
This allows a subset of JS expressions to be checked.
Some JS idioms are not allowed by this system:
- No union types (design choice) - return values, variables, arrays, etc must have a single type. Currently it doesn’t support returning null/undefined either, this can be fixed in the future by adding Optional as a type, but makes principle typing harder.
- No sum types (yet) - this explains why I haven’t added Optional<T>, I think sum types will fit in the type system and are doable. Once added also enums could be expressed.
- Value restriction forbids reassigning to polymorphic variables after declaration (ML-style).
- As a result of the above - can’t use && / || operators like some people do in JS. The operators are required to have the same type on both sides (no allowing “undefined” on one side)
- No type coercion, converting a number to a string (for example) requires using String() constructor.
- And probably other limitations that people might see as a limitation rather than a feature of the type system.
Disclaimer: this type checker comes with NO WARRANTY. I am not a language expert. I didn’t prove soundness, and would love someone who’s an expert to look at it. That being said - it looks correct on all the tests I’ve tried. It’s based on HMF and other published type systems but combines things in a different way.
GitHub: https://github.com/sinelaw/minfern