javascript - 如何在 Map 中使用 `(K | V)[][]` 作为 `ReadonlyArray<[K, V]>`?
问题描述
我想在 Map 构造函数中使用(K | V)[][]
as 。ReadonlyArray<[K, V]>
假设我们的 V 是一个接口IItem
,而 K 是一个基本的number
。
interface IItem {
key: number;
val: string;
}
const items = [[1, {key: 1, val: "a"}]]
const ze_map = new Map<number, IItem>(items);
console.log(JSON.stringify([...ze_map]));
默认情况下,typescript 会将项目的类型视为: (number | IItem)[][]
. 这将不起作用并引发错误:
'(number | { key: number; val: string; })[][]' 类型的参数不能分配给'ReadonlyArray<[{}, {}]>' 类型的参数。
类型 '(number | { key: number; val: string; })[]' 缺少来自类型 '[{}, {}]' 的以下属性:0, 1
对我们来说幸运的是,我们可以强制类型Array<[number, IItem]>
来取悦Map
。
const items2 : Array<[number, IItem]> = [[1, {key: 1, val: "a"}]]
const ze_map2 = new Map<number, IItem>(items2);
console.log(JSON.stringify([...ze_map]));
这项工作符合预期。好吧,让我们转移到我的问题。如果我们不能强制类型怎么办?
const arr = [
{ key: 3, val: 'bar' },
{ key: 5, val: 'world' }
];
const result: Array<[number, IItem]> = arr.map(i => ([i.key, i]));
const ze_map3 = new Map(result);
console.log(JSON.stringify([...ze_map]));
这行不通,因为这里(number | { key: number; val: string; })[][]
不是Array<[number, IItem]>
。那么,如何在 Map中使用(K | V)[][]
as呢?ReadonlyArray<[K, V]>
您可以在线尝试所有代码
我阅读了如何定义具有键类型和值类型之间相关性的 Map,虽然它们都是联合和Typescript Map<enum, set<enum>>“没有重载匹配此调用”,但我不明白为什么?没有找到解决方案。我可能错过了解决方案。
我还阅读了Map 上的 MDN 条目,它说它应该按预期工作,如果你在 vanilla JS 中尝试它会按预期工作:
var arr = [
{ key: 3, val: 'bar' },
{ key: 5, val: 'world' }
];
var result = arr.map(i => [i.key, i]);
const ze_map = new Map(result);
console.log(JSON.stringify([...ze_map]));
解决方案
问题是.map
回调的主体。每当函数返回一个数组时,Typescript 会将返回类型解释为普通数组类型而不是元组类型。
避免as
as
断言会起作用,但它可能很危险,因为它告诉 Typescript “[number, IItem]
即使它真的不是,也要考虑这种类型”,而不是告诉 Typescript “我希望这种类型是这样[number, IItem]
,所以请确保它是。” 在您的情况下,as
不需要,因为它确实是 type [number, IItem]
。我们只需要让 typescript 以这种方式解释它。
设置泛型
最简单的方法是在.map
函数上设置泛型类型参数。这里的泛型变量设置回调的返回类型,所以我们设置为[number, IItem]
.
const result = arr.map<[number, IItem]>(i => [i.key, i]); // result has type [number, IItem][]
const ze_map = new Map(result); // no errors :)
外部化回调
另一种方法是将地图回调定义i => [i.key, i]
为自己的函数,以便您可以注释返回类型。
const toTuple = (i: IItem): [number, IItem] => [i.key, i];
const result = arr.map(toTuple); // result has type [number, IItem][]
const ze_map = new Map(result); // no errors :)
推荐阅读
- javascript - 如何从模拟模块模拟多个值?
- php - 我有一个可以提交的表单,但是当我添加文件上传功能时它不起作用
- java - Spring Data/JPA:如何保存具有多个子集合的项目?
- java - 我有一个休眠问题。启动我的应用程序时速度很慢,使用休眠启动第一个 sessionFactory 需要 2 分钟
- java - iText 7如何为整个文档设置字体
- python - 在 64 位 Mac OSX 上的 64 位 python 解释器上构建“orjson”时,requirement.txt 安装失败
- excel - 我们可以在连接的 Excel 文件打开时修改数据库吗?
- c++ - 什么决定了 constexpr 函数是否是常量表达式?
- r - 外连接与 R 中的条件
- sparql - 如何在 SPARQL (Wikidata) 中任意分组值?