Skip to content

Differences from Fable

Each row is a case in the repository's tests/Differences folder. The differences workflow compiles each case with Fickl and with the latest Fable, runs it with Node.js, and rewrites this table on main. A case leaves the table once Fable passes it too.

What Fickl gets right that Fable 5.27.0 does not, checked by compiling each case in tests/Differences with both and running it with node. A case leaves this table once Fable passes it too.

ChangeFicklFable 5.27.0Issues
Name and FullName of an anonymous record typeAn anonymous record type has a non-empty Name and FullName that tell different anonymous record types apart.compiles, but fails at runtime: expected false, got true#275
explicit constructors in an [<AttachMembers>] classConstructing an [] class through an explicit or secondary constructor runs that constructor.compiles, but fails at runtime: expected 1b, got 1undefined#334
[<AugmentGlobal>] and [<AugmentModule>]An interface marked [<AugmentGlobal>] or [<AugmentModule>] adds its members to a global or module interface in TypeScript, `declare global { interface HT...doesn't compile: Unknown argument: --declaration#154
BigInteger.Parse and TryParse with NumberStylesBigInteger.Parse and TryParse honour the NumberStyles argument, reading HexNumber digits as two's complement, instead of ignoring it or throwing a Ty...compiles, but fails at runtime: The value could not be parsed.#262
[<CallableInterface>]An object expression implementing a callable interface compiles to a plain JavaScript function, and keeps a generic Invoke generic.doesn't type-check: The namespace or module 'Fickl' is not defined.#8, #10, #11
catching values JavaScript throws:? JS.TypeError and the other Fickl.Core.JS error bindings catch JS errors by type, JS.Thrown matches a thrown value that is not an error, and `e.Messa...doesn't type-check: The namespace or module 'Fickl' is not defined.#158
--clampByteArraysCompiles byte arrays as Uint8ClampedArray, the type canvas pixel data uses, so they can be passed to it without a copy.doesn't compile: Unknown argument: --clampbytearrays#39
ResizeArray.Sort, Array.Sort and Comparer<string>.Default on stringsThe .NET comparer paths order strings like String.CompareTo, so lower case sorts before upper case, while F#'s compare and List.sort stay ordinal.compiles, but fails at runtime: expected ["a"; "A"; "b"; "B"], got ["A"; "B"; "a"; "b"]#271
[<Curried>] on a parameterKeeps a function parameter curried, for JavaScript that calls it one argument at a time.doesn't type-check: The namespace or module 'Fickl' is not defined.#24
[<Curried>] on a record fieldKeeps a function stored in a record field curried, for a JS object that stores or calls it one argument at a time.doesn't type-check: The namespace or module 'Fickl' is not defined.#41
functions with more than 20 curried argumentsA function value with more than 20 curried arguments can be passed, called and partially applied.compiles, but fails at runtime: The requested module './fable_modules/fable-library-js.5.27.0/Util.js' does not provide an export named 'uncurry22'#291
Equals and CompareTo on DateOnly, TimeOnly and TimeSpanEquals and CompareTo on DateOnly, TimeOnly and TimeSpan are implemented.compiles, but fails at runtime: The requested module './fable_modules/fable-library-js.5.27.0/DateOnly.js' does not provide an export named 'compareTo'#318
offsets in DateTimeOffset.ParseDateTimeOffset.Parse of an ISO string keeps the offset written in it, not the local one.compiles, but fails at runtime: expected 7200000, got 0#268
out-of-range dates in DateTime parsingDateTime.TryParse rejects a day or month out of range, such as 2020-02-30, instead of rolling it over.compiles, but fails at runtime: expected false, got true#270
--declarationWrites a TypeScript declaration file next to each JavaScript file, so TypeScript can call the compiled F#.doesn't compile: Unknown argument: --declaration#20, #21
a binding with effects before a throwA binding whose value has effects runs where it is declared, not after or inside a later throw.compiles, but fails at runtime: expected ["v"; "threw"], got ["threw"]#408
[<EmitType>]Writes the TypeScript annotation of a type as the given text, for conditional, mapped and template literal types F# cannot describe; the JavaScript is unchan...doesn't compile: Unknown argument: --declaration#145
[<CaseTest>] on erased union casesA JavaScript predicate tells apart erased cases with the same payload type, here two strings.doesn't type-check: The namespace or module 'Fickl' is not defined.#7
option fields ending an erased tupleTrailing option fields of an erased single-case union are optional tuple elements, so FetchArgs("/", None) is ["/"], and named fields label the elements ...doesn't compile: Unknown argument: --declaration#153
operators of an [<Erase>] unionA custom operator of an erased union is used when an operand is built with the case constructor, not the native operator.compiles, but fails at runtime: expected 6, got 3#280
explicit constructors of a class inheriting System.ExceptionA class with only explicit constructors that inherits System.Exception extends it and keeps the message passed to the base.compiles, but fails at runtime: expected boom, got undefined#334
members of a failed Regex matchValue, Index, Length and Groups of a failed match give .NET's empty-match values instead of throwing.compiles, but fails at runtime: Cannot read properties of null (reading '0')—
the FICKL_COMPILER defineDefines FICKL_COMPILER, so code can choose Fickl.Core or Fable.Core when both have an attribute.compiles, but fails at runtime: expected fickl, got fable#43
float rangesEach item of a float range is computed from the start, so rounding errors do not add up and drop the last item.compiles, but fails at runtime: expected 21, got 20—
overloads taking 'T -> 'U and Func<'T, 'U>Overloads that differ only by a function or a delegate parameter get different names.doesn't compile: FABLE: Cannot have two module members with same name: DelegateOverload_Map_5ACDD93#287
importValueDynamic of a functionimportValueDynamic works with tupled and curried functions, called with their compiled signature.doesn't compile: FABLE: The imported value is not coming from a different file#314
[<InlineInterface>]A TypeScriptTaggedUnion case holding one interface compiles as that interface with the tag added, { type: "take", fromIndex, toIndex }.doesn't type-check: The namespace or module 'Fickl' is not defined.—
Int32.Parse with signs, radix prefixes and underscoresInt32.Parse rejects 0x, 0b, 0o and _ as .NET does, and with HexNumber takes neither a sign nor a 0x prefix.compiles, but fails at runtime: expected true, got false#261
[<JsError>]An F# exception marked [<JsError>] is a JS Error subclass with a stack, and still matches and compares as an F# exception.doesn't type-check: The namespace or module 'Fickl' is not defined.#157
members of a class inheriting a JavaScript classA class whose base is a global or imported JavaScript class attaches its members, so JavaScript sees static observedAttributes and its methods.compiles, but fails at runtime: Cannot read properties of undefined (reading '0')#162
--temporalRepresents dates and times with the JavaScript Temporal API, a documented flag for Fable's hidden --test:js-temporal.doesn't compile: Unknown argument: --temporal#39
keyof<'T> and keyof<'T, 'R> property keyskeyof _.Port is the property's JavaScript name, typed keyof T & string or KeysOfType<T, R> in TypeScript, and KeyOf.get/KeyOf.set index an object b...doesn't compile: Unknown argument: --declaration#174
Match.NextMatch()Match.NextMatch() is implemented, resuming the search after the current match.compiles, but fails at runtime: The requested module './fable_modules/fable-library-js.5.27.0/RegExp.js' does not provide an export named 'nextMatch'#343
copying a mutable struct record{ m with ... } and a byref to a mutable struct record read the struct's fields, not those of a reference cell.compiles, but fails at runtime: expected , got#254
--nativeErrorsEvery exception, from failwith to a declared F# exception, is a JS Error with a stack, and an inner exception is its cause.doesn't compile: Unknown argument: --nativeerrors#157
[<NoOverloadSuffix>]Drops the overload hash from a method's compiled name, Counter__Add instead of Counter__Add_Z524259A4, so JavaScript can call it by a predictable name. O...doesn't type-check: The namespace or module 'Fickl' is not defined.#35
partial and Partial<'T>partial builds an object with some of a type's properties, typed Partial<T> and checked with satisfies in TypeScript instead of cast to the full type.doesn't compile: Unknown argument: --declaration#151
an explicit class inheriting a class with a primary constructorThe class extends its base, so { inherit Base("derived"); Extra = 5 } has its Name.compiles, but fails at runtime: expected derived, got undefined#96
let fields of a class inheriting a JavaScript classThe fields are ES #private fields, so let size in a subclass of Map does not try to set Map's read-only size.compiles, but fails at runtime: Cannot set property size of # which has only a getter#161
--privateFieldsCompiles the let fields of every class with attached members to ES #private fields, which JavaScript cannot read or enumerate.doesn't compile: Unknown argument: --privatefields#161
indexing an IReadOnlyList<'T>xs.[i] on an IReadOnlyList indexes an array, a ResizeArray or an F# list instead of calling a .NET member name that arrays do not have.compiles, but fails at runtime: xs.System.Collections.Generic.IReadOnlyList`1.get_ItemZ524259A4 is not a function#431
read-only collections in TypeScript annotationsIReadOnlyCollection, IReadOnlyList and IReadOnlyDictionary are annotated as types a TypeScript readonly array or ReadonlyMap satisfies instead of `an...doesn't compile: Unknown argument: --declaration#146
ReflectedDecorator member namesThe MethodInfo given to a ReflectedDecorator has the member's own name, not the mangled declaration name.compiles, but fails at runtime: expected ["decorated function"; "StaticMember"], got ["decorated$0020function"; "Decorated_StaticMember_Z524259A4"]#276
[<ReturnsThis>]An abstract method returning its own interface is declared returning this in TypeScript, so a subinterface keeps its members through a chain of calls; the ...doesn't compile: Unknown argument: --declaration#152
--strictOptionsSome null of a string, array, class, record or function stays Some, as on .NET, built the same way at concrete and generic sites. Value options stay erased.doesn't compile: Unknown argument: --strictoptions#32
[<StructuredFormatDisplay>]%A, %O, string and interpolation print a record or union with its [] format.compiles, but fails at runtime: expected Foo , got#266
TimeSpan ticksTimeSpan.FromTicks keeps sub-millisecond ticks and reads back Int64.MaxValue, and ToString prints all seven fraction digits.compiles, but fails at runtime: expected 1, got 0#264
[<TsEnum>] and imported [<StringEnum>] unionsEmits a [<TsEnum>] enum as the object a TypeScript enum compiles to, typed by an ambient enum in TypeScript, and compiles the cases of an imported or globa...doesn't type-check: The namespace or module 'Fickl' is not defined.#149
Record<'K, 'V>, ReadonlyRecord and PropertyRecordFickl.Core.Record<'K, 'V> is a plain object typed Record<K, V> in TypeScript, with ReadonlyRecord and PropertyRecord for Readonly<Record<K, V>> and...doesn't compile: Unknown argument: --declaration#175, #142
unknown, an abbreviation of objA module function or abstract member taking or returning Fickl.Core.unknown has unknown in its TypeScript signature, so TypeScript callers must narrow th...doesn't compile: Unknown argument: --declaration#150
[<TypePredicate>] and [<TypeAssertion>]Emits a function as a TypeScript type guard, x is T or asserts x is T, while F# calls it as returning an option or a Result of the narrowed argument.doesn't type-check: The namespace or module 'Fickl' is not defined.#147
a function parameter passed to ==> or ?<-A two-argument function that reaches ==> or ?<- through a member parameter is uncurried, so JavaScript can call it with two arguments.compiles, but fails at runtime: expected member 1 x, got (a2) => f(a1, a2)#289
valueof<'T> for T[keyof T]Fickl.Core.valueof<'T> is the value of some property of 'T, typed T[keyof T] in TypeScript, built with ValueOf.ofKey and read as a type with a visibl...doesn't compile: Unknown argument: --declaration#177
Edit this page