typeskin

0.1.1 • Public • Published

TypeSkin

A lightweight, drop-in layer on top of JavaScript which gives it an expressive, static type system. Differently from TypeScript, it:

  1. Doesn't require another language, thus, can be dropped-in to type a critical function or two;

  2. Has zero runtime cost (if you don't enable runtime checks, obviously);

  3. Allows you to express very precise types such as "the type of hex-encoded strings with an even number of characters", and can statically check all of them;

  4. Performs automatic invariant-based tests, similarly to Haskell's QuickCheck, giving you a very high level of safety with minimal dev effort.

Since checking is based on random sampling, it is not a real type-system, in the sense it can't give you a guarantee of correctness, like TypeScript would. But that's not its job: its job is to spot, at compile time, a very large class of common programmings mistake. For that purpose, it actually performs very well, catching a larger class of bugs than TypeScript ever could.

Static type checks

The basic idea is that, when declaring a JavaScript value or function, instead of doing it as usual:

// Receives a Buffer()-compatible byte-string, returns its byte count
const countBytes = function(a) {
  return bytes.length / 3;
}

You can, optionally, wrap it with a type annotation:

// A function from numbers to numbers
const countBytes = T(T.Fn(T.Bytes, T.Uint32),
  function(bytes) {
    return bytes.length / 3;
  });

And then run (i.e., "compile") your module with node myLib.js. TypeSkin will statically check your declarations:

type mismatch

That error is shown because "1" + x is a String, not a Number, as annotated. Once everything checks, your program behaves exactly the same as if TypeSkin wasn't there at all. And that's it!

Rich type language

TypeSkin allows you to define rich types, using an expressive dialect. Here is, for example, a type for Pokémon:

const T = require("TypeSkin");
 
// A Pokémon Type
const Type = T.Enum(
  "normal" , "fight"   , "flying" , "poison"   ,
  "ground" , "rock"    , "bug"    , "ghost"    ,
  "steel"  , "fire"    , "water"  , "grass"    ,
  "dragon" , "psychic" , "ice"    , "electric" ,
  "dark"   , "fairy"
).__name("Type");
 
// A Pokémon Stat
const Stat = T.Enum(
  "hp"  , "atk" , "def",
  "spe" , "spa" , "spd"
).__name("Stat");
 
// A Pokémon
const Pokemon = T.Struct({
  name: T.String,
  number: T.Uint16,
  types: T.Pair(Type, T.Maybe(Type)),
  attacks: T.Vector(4, T.String),
  stats: T.Struct({
    hp: T.Uint8,
    atk: T.Uint8,
    def: T.Uint8,
    spe: T.Uint8,
    spa: T.Uint8,
    spd: T.Uint8
  })
}).__name("Pokemon");
 
// A function that receives a Pokémon and returns an Uint8
const highestStat = T(
  T.Fn(Pokemon, T.Uint8),
  function(poke) { 
    return Math.max(
      poke.stats.hp,
      poke.stats.atk,
      poke.stats.spe,
      poke.stats.spa,
      poke.stats.spd); 
  })

Notice the presence of enums, several integer types, pairs, structs, a fixed-size vector and even Haskell's Maybe. Types are plentiful and everything is checked statically. Try "compiling" the file above and changing some bits!

Invariants

The code above, while well-typed, is wrong. Let's add another line to it:

T.forall([Pokemon, Stat], (poke, stat) => highestStat(poke) >= poke.stats[stat]);

This declaration says that, for every Pokémon, we expect that its highestStat is at least as large as any of its stats - which is obvious, isn't it? Let's "compile" that file again:

invariant violation

Woops! It is telling us that our invariant doesn't hold for the def stat of ketecape, a Pokémon randomly generated from its type, which happens to have its def as the highest stat. Seems like we forgot to add poke.stats.def to our highestStat function! Invariants are very similar to tests, as they spot mistakes even on well-typed code. They're easy to write and can be very specific, providing a powerful sense of safety.

Learning

The best way to learn TypeSkin is by following the TypeSkin game.

Readme

Keywords

none

Package Sidebar

Install

npm i typeskin

Weekly Downloads

1

Version

0.1.1

License

MIT

Last publish

Collaborators

  • maiavictor