如何在类型参数中使用展开的多态变体[union type]



目标:绑定到Service Worker缓存

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

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

我对[@bs.unwrap]的了解

我知道我可以像一样使用[@bs.unwrap]为add方法编写绑定

[@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中建模吗

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

但现在我很好奇:有没有一种方法可以在ReScript中对绑定中的这种类型进行建模?

您可以使用一个抽象类型和一组转换函数来"铸造";值,而不是多态变体:

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食谱中摘录的,其中还有很多其他食谱,在这种棘手的情况下可能会派上用场。

相关内容

  • 没有找到相关文章

最新更新