Open sydsutton opened 11 months ago
@sydsutton Not supported yet at the moment, no. It does makes sense to add optional support for JS tuples and records, once they are more widely supported. I'll tag this as a feature request.
In the mean time, is it possible to wrap the tuple arrays in Tuple.from
?
I know it's probably a bad work-around, so only as a temporary solution.
@ncave Thanks for the quick response! I'll give it a shot. What namespace would Tuple.from
be under?
@sydsutton Technically it should be in Fable.Core.JS
, but those new primitives are not there yet.
You can perhaps directly emit the new tuples where you need them:
let makeTupleInit x = Fable.Core.JsInterop.emitJsExpr (x) "#$0"
let makeTupleFrom x = Fable.Core.JsInterop.emitJsExpr (x) "Tuple.from($0)"
let t1 = (2, "three", 4)
let t2 = makeTupleInit (2, "three", 4)
let t3 = makeTupleFrom t1
will compile to:
const t1 = [2, "three", 4];
const t2 = #[2, "three", 4];
const t3 = Tuple.from(t1);
BTW, do you have a link to which browser support is already there for Tuples and Records, or is it still in preview? Somehow I can't find it, at least there is none in Node.js yet.
No, I am not sure about browser support, but I have been successfully using tuples for functions in my project for a while now just by using partial application. Thanks for the response, btw.
@sydsutton I guess my question was, what JavaScript engine have you used those new #Tuples with? Somehow I can't find any references to actual support, besides a few articles about a preview spec.
It seems like Tuple
in JavaScript are still in Stage 2: Draft and Can I use doesn't report any results.
So I don't think tuple are yet widely spread meaning that their implementation is subject to change. We can't add support for it in Fable directly, because we don't know if this going to be implemented or not in the future. And also, if the specification change then we would need to introduce breaking changes.
I summarised Ncave utilities + another example in this REPL link.
open System
open Fable.Core
open Fable.Core.JsInterop
// You could place this module under your own Fable.Core.JS modules
// for consistance
module JS =
let inline makeTupleInit x = Fable.Core.JsInterop.emitJsExpr (x) "#$0"
let makeTupleFrom x = Fable.Core.JsInterop.emitJsExpr (x) "Tuple.from($0)"
[<Erase>]
type Test =
static member inline mergeClasses (classNames : 'T) = import "mergeClasses" "FluentUIv9"
static member inline mergeClasses (v1 : 'T, v2 : 'T) =
Test.mergeClasses (JS.makeTupleInit (v1, v2))
static member inline mergeClasses (v1 : 'T, v2 : 'T, v3 : 'T) =
Test.mergeClasses (JS.makeTupleInit (v1, v2, v3))
let style =
("red", "bold")
Test.mergeClasses style
Test.mergeClasses (JS.makeTupleFrom style)
Test.mergeClasses (JS.makeTupleInit style) // Not sure if this works
Test.mergeClasses (JS.makeTupleInit ("red", "bold")) // Seems to generate the correct output
Test.mergeClasses ("red", "bold")
Test.mergeClasses ("red", "bold", "underline")
Another solution to add support for Tuple in your project, could be by using a Fable compiler plugin. Like Feliz does for React, but it needs more works and it is not well documented yet.
@MangelMaxime @ncave Great, thank you guys for the responses. I really appreciate the help.
I have encountered the same issue because VanJS api heavily depends on n-ary functions that I need to use.
My workaround is to create a bridge.js and export the hooked functions like this
import van from 'vanjs-core'
// unary function ([a,b,c,...]) in F#
// -> n-ary function (a,b,c,...) in VanJS
let n =
f => array =>
f(...array);
export let tags =
new Proxy(van.tags, {
get: (target, property) => {
return n(target[String(property)]);
}
});
export let add = n(van.add);
then imports from *.fs
open Fable.Core.JsInterop
let tags: obj
= importMember "../ts/tags_add"
let add: List<obj> -> Element
= importMember "../ts/tags_add"
Thanks, @ken-okabe ! I'll see if I can figure out something similar for my project.
I'm sorry, but probably, I misunderstood your question. As already mentioned here, JS/TS currently does not have tuple data structure, so in theory, "Generate JS tuple" is impossible.
In JS, (a, b, c)
is not a value, but f(a, b, c)
means n-ary function that takes multiple arguments.
My workaround is just convert
f [a, b, c]
in F#
to
f (a, b, c)
in JS
Description
I was wondering if there are any configuration options for me to purposefully produce a JS (or TS) tuple from an F# tuple instead of a JS array from F# tuple? I'm working on an F# front-end library, and need a tuple for this particular implementation. Thanks!
Function:
static member inline mergeClasses (classNames: 'T): string = import "mergeClasses" FluentUIv9
Usage:
prop.className (Fui.mergeClasses (styles.backgroundColor, styles.textColor, styles.borderRadius))
Fable compilation:
createObj(ofArray([["className", mergeClasses([styles.backgroundColor, styles.textColor, styles.borderRadius])]
Expected and actual results
The code works as it should if Fable were to compile it into:
createObj(ofArray([["className", mergeClasses(styles.backgroundColor, styles.textColor, styles.borderRadius)]
(no array)Related information
4.1.4