Как использовать развернутый полиморфный вариант [тип объединения] в параметре типа?

Цель: привязка к кешу Service Worker

Я пишу привязку, позволяющую писать Service Workers на ReScript. Строковые URL-адреса и запросы иногда используются как взаимозаменяемые.

По возможности я избегаю шума в выводе JS.

Что я знаю о [@bs.unwrap]

Я знаю, что могу написать привязку для чего-то вроде метода добавления, используя [@bs.unwrap] вот так

[@bs.send]
  external add: (cache, [@bs.unwrap] [ `Request(Request.t) | `String(string)])
  => Js.Promise.t(unit) = "add";

Это простое использование.

Проблема: привязка с array запросов и / или строк

AddAll метод, однако, имеет более сложный вид подписи. Требуется массив объектов, который может быть массивом или запросами, или массивом строк, или массивом, содержащим оба типа элементов.

Но насколько мне известно, вы не можете распаковать тип внутри параметра типа, например

[@bs.send]
  external addAll: (cache,
   array([@bs.unwrap] [ `Request(Request.t) | `String(string)])
  => Js.Promise.t(unit) = "addAll";

Вопрос: Можно ли моделировать такую ​​привязку в ReScript?

Конечно, было бы разумно просто отказаться от строкового случая и использовать запросы или написать две отдельные привязки и предположить, что мне не понадобится массив, в котором есть оба.

Но теперь мне просто любопытно: есть ли способ смоделировать такой тип ввода в привязке в ReScript?

1 ответ

Решение

Вы можете использовать абстрактный тип и набор функций преобразования для "приведения" значений к этому типу вместо полиморфного варианта:

module Value = {
  type t;
  external request: Request.t => t = "%identity";
  external str: string => t = "%identity";
};

[@bs.send]
  external addAll: (cache, array(Value.t)) => Js.Promise.t(unit) = "addAll";

Пример использования:

addAll(cache, [|
  Value.request(req),
  Value.str("foo"),
|])

или используя local open для краткости:

addAll(cache, Value.[|
  request(req),
  str("foo"),
|])

Вот как Js.Jsonкодировщики тоже работают, если вы когда-нибудь задумывались. И с тех пор Js.Jsonтакже есть декодеры, вы знаете, что можно пойти другим путем, если вам когда-нибудь понадобится. Однако это немного сложнее и зависит от базовых типов, которые были абстрагированы.

Кстати, это взято из моей кулинарной книги BuckleScript, в которой также есть немало других рецептов, которые могут пригодиться в таких сложных ситуациях, как эта.

Другие вопросы по тегам