.NET and F# Compatibility
.NET Base Class Library
The following classes are translated to JS and most of their methods (static and instance) should be available in Fable.
|Arrays||Array / Typed Arrays|
|System.Math||(native JS functions)|
The following static methods are also available:
System.Console.WriteLine(also with formatting)
System.Diagnostics.Debug.WriteLine(also with formatting)
There is also support to convert between numeric types and to parse strings, check the convert tests.
- All numeric types become JS
number(64-bit floating type), except for
bigint. Check this document to learn more about the differences in numeric types between .NET and JS.
- Numeric arrays are compiled to Typed Arrays when possible.
- No bound checks for numeric types (unless you do explicit conversions like
byte 500) nor for array indices.
Regexwill always behave as if passed
RegexOptions.ECMAScriptflag (e.g., no negative look-behind or named groups).
Most of FSharp.Core operators are supported, as well as formatting with
String.Format is also available).
The following types and/or corresponding modules from FSharp.Core lib will likewise translate to JS:
|Arrays||Array / Typed Arrays|
|MailboxProcessor||fable-core/MailboxProcessor (limited support)|
The following F# semantic and syntactic features are also available:
- Records and Unions
- Structural Equality/Comparison
- Comprehensions (seq, array, list)
- Computation Expressions
- Pattern Matching
- Active Patterns
- Object Expressions
- Units of measure
- Options are erased in JS (
Some 5becomes just
5in JS and
null). This is needed for example, to represent TypeScript optional properties. However in a few cases (like nested options) there is an actual representation of the option in the runtime.
Async.RunSynchronouslyis not supported.
MailboxProcessoris single-threaded in JS and currently only
PostAndAsyncReplyare implemented (
timeoutoptional arguments are not supported).
Object Oriented Programming
Classes translate to ES6 classes and most of their .NET/F# characteristics are available: properties, overloads, secondary constructors, custom operators, etc.
Inheritance is possible and conforms to ES2015 inheritance but must be done by calling the primary constructor of the base class. Methods can be overridden and call the base implementation. Just note it won't be possible to access the base implementation from outside by casting the object. Example:
type A() = member x.Foo() = "Hello" type B() = inherit A() member x.Foo() = base.Foo() + " World!" // This prints "Hello World!" both in .NET and JS B().Foo() |> printfn "%s" // This prints "Hello" in .NET and "Hello World!" in JS (B() :> A).Foo() |> printfn "%s"
Interface methods are compiled as normal object methods and it's possible to test against an interface (e.g.
x :? IComparable) for types defined in F# code.
Generics are erased by default in generated code. However, it is still possible to access generic information in inline functions (like
typeof<'T>) or methods decorated with
Caveat: Functions decorated with
PassGenericsAttributemay work unexpectedly if called from external JS code.