F# Fable 和 JS 互操作:不安全列表转换

F# Fable and JS interop: unsafe list casting

我不确定我是否在 Fable 的 interface/compiler 中发现了错误,或者我误用了类型 system/externs。

今天我遇到了一个非常令人沮丧的错误。像往常一样,我将 externs 键入我用 JS 编写的小函数,其中一个从 NOSQL 数据库返回对象列表。显然寓言收到了很好的对象。但是,当我尝试转换对象时,代码以不一致的方式没有任何错误或解释就死了。

因为代码很复杂,包含 promises、解析和其他移动部分,我花了很多时间才找出有罪的部分和原因,但最后我意识到 JS 数组没有正确匹配 F# 列表,这是唯一的方法我发现继续前进的内容如下:

type IJSInterface =
    abstract FetchPosts: string -> JS.Promise<DBPost list>

...

// Transform Javascript array to F# normal list
let postList = straightJSArrayWithTypedPosts |> List.toArray |> Array.toList

我的问题是:与 javascript 数组交互的推荐方式是什么?因为我阅读了所有可能的文档,但找不到关于这部分的任何精确说明。我个人认为它更像是一个错误。事实上,我希望我可以通过编译器错误禁止此 "feature" 或在 javascript 和 F# 之间立即进行数组安全互操作。有这样的编译器选项吗?编译器怎么能避免让我在这些问题上花费整个星期天呢?有什么flag什么的吗?


编辑:正如答案中所猜测的那样,省略的 javascript 代码实际上返回了一个 javascript array ,它与 list,虽然两者非常相似,但尽管在大多数情况下表现相同,但它们并不相同 在动态语言中

如果我对问题的理解正确,问题是您的 JavaScript API 正在返回数组,但您希望将它们视为 F# 列表。

Fable 中外部 API 类型的工作方式是您必须定义类型 "as it is generated by external JavaScript API"。编译器不会进行任何转换,也不会尝试在运行时检查它,因此您只需要正确处理即可。如果您在实际 JavaScript API 生成数组的地方使用 list,那么您输入的外部库是错误的。

所以,在这种情况下,我认为你应该使用:

type IJSInterface =
    abstract FetchPosts: string -> JS.Promise<DBPost[]>

这会让您的 F# 变得不太好用 API,但是当您调用 JavaScript 代码时这是可以预料的。