Fable is a compiler powered by Babel designed to make F# a first-class citizen of the JavaScript ecosystem

FableConf 2019 is happening in Antwerp on September 6/7th. Get your ticket soon!

Functional programming and more

Immutable by default. Powerful pattern matching. Lightweight syntax. Units of measure. Type providers. Enjoy!

Type safety without the hassle

Don't panic about verbose signatures. Let the compiler infer the types and catch the bugs for you before they ever get into runtime!

Modern Javascript output

Fable produces readable JavaScript code compatible with ES2015 standards and popular tooling like Webpack!

Quick start

Try Fable online or get started in your local machine with our set of samples (more info):

  1. Install .NET Core SDK
  2. Install Node.js
  3. Then type in a terminal:
git clone https://github.com/fable-compiler/fable2-samples
cd fable2-samples/browser  
npm install
npm start

Features

These are some of the main F# features that you can use in your web apps with Fable.


Powerful pattern matching

Model your domain with union types and match complex patterns with ease. The compiler will warn you if you're forgetting some cases!


type Face = Ace | King | Queen | Jack | Number of int
type Color = Spades | Hearts | Diamonds | Clubs 
type Card = Face * Color

let aceOfHearts = Ace,Hearts
let tenOfSpades = (Number 10), Spades

match card with 
| Ace, Hearts -> printfn "Ace Of Hearts!"
| _, Hearts -> printfn "A lovely heart"
| (Number 10), Spades -> printfn "10 of Spades"
| _, (Diamonds|Clubs) -> printfn "Diamonds or clubs"
// warning: Incomplete pattern matches on this expression.
// For example, the value '(_,Spades)' may indicate
// a case not covered by the pattern(s).

Computation expressions

There's a lot of code involving continuations out there, like asynchronous or undeterministic operations. Other languages bake specific solutions into the syntax, with F# you can use built-in computation expressions and also extend them yourself.


// JS promises made easy
promise {
    let! res = Fetch.fetch url []
    let! txt = res.text()
    return txt.Length
}

// Declare your own computation expression
type OptionBuilder() =
  member __.Bind(opt, binder) =
    match opt with Some value -> binder value | None -> None
  member __.Return(value) = Some value

let option = OptionBuilder()

option {
  let! x = trySomething()
  let! y = trySomethingElse()
  let! z = andYetTrySomethingElse()
  // Code will only hit this point if the three
  // operations above return Some
  return x + y + z
}

Units of measure

Let the compiler verify arithmetic relationships for you to help prevent programming errors.


[<Measure>] type m
[<Measure>] type s

let distance = 12.0<m>
let time = 6.0<s>

let thisWillFail = distance + time 
// ERROR: The unit of measure 'm' does 
// not match the unit of measure 's'

let thisWorks = distance / time
// 2.0<m/s>

Type providers

Build your types using real-world conditions and make the compiler warn you if those conditions change.


let [<Literal>] JSON_URL = "https://jsonplaceholder.typicode.com/todos"

// Type is created automatically from the url
type Todos = Fable.JsonProvider.Generator<JSON_URL>

async {
    let! (_, res) = Fable.SimpleHttp.Http.get url
    let todos = Todos.ParseArray res
    for todo in todos do
        // If the JSON schema changes, this will fail compilation
        printfn "ID %i, USER: %i, TITLE %s, COMPLETED %b"
            todo.id
            todo.userId
            todo.title
            todo.completed
}

Users of Fable

These are some of the projects and companies using Fable. Send us a message to include yours!