如何使用 TypeScript 中的 List、Map 等

How to use List, Map, etc. from TypeScript

我有一个 ReScript 和 TypeScript 组合项目。我想使用 gentype 来公开 TypeScript 友好对象。 Gentype 适用于字符串、布尔值、记录和其他基本对象,没有任何麻烦。我如何使用 TypeScript 中的 listchar 以及其他特定于 ReScript 的类型?

有垫片功能,但我不知道该怎么做。我假设标准 Belt 库有内置垫片,但找不到它们。

我计划在 Rescript 中完成大部分计算和繁重的工作。所以当信息被发送到 TypeScript 时,我可能只是在使用数据,而不是修改它。这可能会遍历列表以显示非 Rescript React 项目中的内容。我不打算操纵数据。

一个选项是在导出结果之前在 ReScript 中将列表转换为数组。因此,每当我想使用来自 TypeScript 的信息时,我都会在 ReScript 中创建一个 and/or 类型的函数,它只有 bool、number、string、array 和 object。我可以创建一个“互操作”模块,其中包含我想从 TypeScript 消费或使用的所有内容。这在 ReScript 和 TypeScript 世界之间提供了一个清晰的分离,很容易理解,但似乎有点低效(比如将所有列表转换为数组)和额外的工作。

另一方面,如果使用 TypeScript 中的 Belt 对象(如 list 和 map)很麻烦,即使有垫片,那么我最好还是创建我的“互操作”模块。

在 TypeScript 中使用 list、map、char 和其他 ReScript 特定对象的 recommended/simplest/best 方法是什么?即使我没有使用 ReScript,我也可以使用 Belt 标准库的友好 Typescript 定义吗?

===

一个补充说明。我有尝试从 C# 使用 F#(函数式)的经验。这很痛苦。在那个环境中,对我来说最好的解决方案是在 F# 端创建一个接口,该接口可以在不使用 F# 本机对象的 C# 端轻松使用。

由于 rescript 编译为 JavaScript,并且输出非常易读且(通常)直截了当,您可以模拟它生成的内容。

比如这个重写代码:

let xs = list{1, 2, 3}
let _ = List.map(x => x + 1, xs)

编译成这样(稍微简化)JavaScript:

var List = require("./stdlib/list.js");

var xs = {
  hd: 1,
  tl: {
    hd: 2,
    tl: {
      hd: 3,
      tl: /* [] */0
    }
  }
};

List.map((x) => x + 1, xs);

列表的字面语法有一个小问题,但可以通过使用 List.cons 来简化:

let xs = List.cons(1, List.cons(2, List.cons(3, list{})))

变成:

var xs = List.cons(1, List.cons(2, List.cons(3, /* [] */0)));

模式匹配显然也不是那么方便,但至少对于简单的事情来说仍然非常简单。例如:

let rec sum = xs => switch xs {
  | list{} => 0
  | list{x, ...rest} => x + sum(rest)
}

变成:

function sum(xs) {
  if (xs) {
    return xs.hd + sum(xs.tl);
  } else {
    return 0;
  }
}

大多数其他类型没有任何特殊的编译器支持,因此只是普通的函数调用。例如,使用 Belt.Map,尽管使用了一些高级语言功能,编译为非常直接的 JavaScript:

module IntCmp = Belt.Id.MakeComparable({
  type t = int
  let cmp = (a, b) => a - b
})

let m = Belt.Map.make(~id=module(IntCmp))
let _ = Belt.Map.set(m, 0, "a")

变成(或多或少):

var Belt_Id = require("./stdlib/belt_Id.js");
var Belt_Map = require("./stdlib/belt_Map.js");

var IntCmp = Belt_Id.MakeComparable({
      cmp: (a, b) => a - b
    });

var m = Belt_Map.make(IntCmp);
Belt_Map.set(m, 0, "a");