F # Fable и JS interop: небезопасное приведение списка - PullRequest
1 голос
/ 27 апреля 2020

Я не уверен, нашел ли я ошибку в интерфейсе / компиляторе из Fable или неправильно использовал тип system / externs.

Сегодня я получил очень расстраивающую ошибку. Как обычно, я набирал externs для небольших функций, написанных в JS, и одна из них возвращала список объектов из базы данных NO SQL. Видимо басня получила объект хорошо. Однако когда я попытался преобразовать объект, код умер без каких-либо ошибок или объяснений непоследовательным образом.

Поскольку код был сложным с обещаниями, анализом и другими движущимися частями, мне потребовалось много часов, чтобы выяснить виновного часть и причины, но в конце концов я понял, что массив 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 массивами? Потому что я прочитал всю документацию, которую мог, и не смог найти точных инструкций по этой части. И лично я вижу это больше как ошибку. На самом деле, я sh мог бы запретить эту "функцию" из-за ошибок компилятора или иметь немедленное безопасное взаимодействие с массивами между javascript и F #. Есть ли такая опция компилятора? Как мог компилятор избежать такого целого воскресенья? Есть ли какой-нибудь флаг или что-то еще?


Редактировать: как и предполагалось в ответе, пропущенный код javascript фактически возвращал массив javascript , который не совпадает с список , хотя оба они очень похожи, они не одинаковы, несмотря на то, что ведут себя одинаково для большинства целей в динамических c языках .

1 Ответ

2 голосов
/ 27 апреля 2020

Если я правильно понял вопрос, проблема в том, что ваш JavaScript API возвращает массивы, но вы хотели бы вместо этого просматривать их в виде списков F #.

Способ работы внешних API-интерфейсов в Fable заключается в том, что вы должны определить тип «как он генерируется внешним JavaScript API». Компилятор не будет выполнять никаких преобразований и не будет пытаться проверить это во время выполнения, поэтому вам просто нужно сделать это правильно. Если вы используете list в месте, где фактический JavaScript API генерирует массив, то вы неправильно набираете внешнюю библиотеку.

Так что, в этом случае, я думаю, вы должны просто использовать:

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

Это дает вам несколько менее приятный F # API, но этого следует ожидать при вызове JavaScript кода.

...