如何使用 TypeScript 中的 List、Map 等
How to use List, Map, etc. from TypeScript
我有一个 ReScript 和 TypeScript 组合项目。我想使用 gentype
来公开 TypeScript 友好对象。 Gentype 适用于字符串、布尔值、记录和其他基本对象,没有任何麻烦。我如何使用 TypeScript 中的 list
和 char
以及其他特定于 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");
我有一个 ReScript 和 TypeScript 组合项目。我想使用 gentype
来公开 TypeScript 友好对象。 Gentype 适用于字符串、布尔值、记录和其他基本对象,没有任何麻烦。我如何使用 TypeScript 中的 list
和 char
以及其他特定于 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");