OSSSoftware DevelopmentUncategorized

Getting Fable to Work with JavaScript Libraries for Functions with Multiple Arguments

By January 19, 2017 No Comments

Fable is a transpiler that allows you to code front-end and back-end JavaScript with the type-safety and elegant syntax of FSharp. Prolucid relies on Fable for front-end web work in many production projects such as E2C Configure.

One important aspect of using Fable is being able to interact with the JavaScript ecosystem. To facilitate that, there are times that you need to understand how Fable generates JavaScript code, especially when considering exposed interfaces in your application.

The Problem

A problem I’ve run into several times is Fable generating a JavaScript function that doesn’t match the signature that an external resource is expecting.

For example, let’s say we are trying to hook up a callback mechanism like SignalR, in which a server-side callback to the client is illustrated as:

myHub?gotData(param1, param2)

SignalR ends up generating a JavaScript proxy, which gets hooked up by setting a corresponding function in JavaScript:

myHub.client.gotData = function(param1, param2) { ... }

In F#, you would do something similar:

myHub.client.gotData <- (fun param1 param2 -> ...)

However, this transpiles into curried form:

myHub.client.gotData = function(param1) { return function(param2) { ... }; }

Perhaps this is justified, since the F# function is in curried form, however the SignalR proxy will try to call gotData(param1, param2), which will not work. One thought might be to try a tupled version of the callback in F#:

myHub.client.gotData <- (fun (param1, param2) -> ...)

However, Fable converts a tuple list into an array, which leaves SignalR with the same problem:

myHub.client.gotData = function(params) { var param1 = params[0]; var param2 = params[1]; }

The Solution

The author of Fable goes into more detail in this stackoverflow post. Long story short, if the lambda is cast to a System.Func<>, Fable will no longer transpile into the curried form and the JavaScript output will be as expected.