1

目标:绑定到Service Worker 缓存

我正在编写一个绑定,让我在 ReScript 中编写 Service Worker。字符串 URL 和Request有时可以互换使用。

在可能的情况下,我会避免 JS 输出中的噪音。

我对[@bs.unwrap]的了解

我知道我可以像这样使用add方法编写绑定[@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 中建模吗?

当然,放弃字符串大小写并使用 Requests 或编写两个单独的绑定并假设我不需要同时具有两者的数组是合理的。

但现在我只是好奇:有没有办法在 ReScript 的绑定中对这种类型的类型进行建模?

4

1 回答 1

2

您可以使用抽象类型和一组转换函数将值“转换”为该类型,而不是多态变体:

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"),
|])

或为简洁起见使用本地开放:

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

这也是Js.Json编码器的工作方式,如果您曾经想知道的话。而且由于Js.Json也有解码器,因此您知道如果需要,也可以采用其他方式。这样做有点复杂,并且取决于已经抽象出来的底层类型。

顺便说一句,这是从我的 BuckleScript 食谱中摘录的,它还有很多其他的食谱,在这种棘手的情况下可能会派上用场。

于 2020-11-29T00:06:52.590 回答