如何在打字稿中将 array.map 与元组一起使用?

2024-01-07

每当我使用array.map对于元组,Typescript 将其推断为通用数组。例如,以下是简单 3x3 数独游戏的一些片段:

const _ = ' ' // a "Blank"

type Blank = typeof _

type Cell = number | Blank

type Three = [Cell, Cell, Cell]

type Board = [Three, Three, Three]

const initialBoard: Board = [
    [_, 1, 3],
    [3, _, 1],
    [1, _, _],
]

// Adds a `2` to the first cell on the first row
function applyMove(board: Board): Board {
    // ????errors here
    const newBoard: Board =  board.map((row: Three, index: number) => {
        if (index === 0) return <Three> [2, 1, 3]
        return <Three> row
    })
    return newBoard
}

function applyMoveToRow(row: Three): Three {
    // return [2, 1, 3] // This works
    const newRow: Three = [
        2,
        ...row.slice(1, 3)
    ]
    return newRow
}

TS 错误为:

Type '[Cell, Cell, Cell][]' is missing the following properties from type 
 '[[Cell, Cell, Cell], [Cell, Cell, Cell], [Cell, Cell, Cell]]': 0, 1, 2 .  

here http://www.typescriptlang.org/play/#code/MYewdgzgLgBA+jAvDA5KmB6DMCGMBEAQgDY5gDW+AsAFC1QCeADgKYwlnlIyOsgBm8WvWZsAwi2LFuYAK4BbAEYsATjAA+7UhWE1ebACoALFSzbIA2hKkAaGNeJ2HAXV372IHCoAm3C8dMWOwCzYJMzVzoaUEhYAEswOKg4nGJCTx8ALg8vX0taGEKYCzg7AEY7AGZnGwKii0q7UpgymrrCiwr4JraaSNosGABBb28IXBgAAwAmSZ4QHiM2fjiVaBhgSWlwReXV9ZUQAHdaflkwYGSdnCYmYgYAWRAANxYACkUM72z03IBKH5fGAAb3aG3A6zALCOvyyOR83Bgn1yADp5Dc3m9DkdsiEgjAEt4WAAPbJyJSqP5IAB8ILBRQJgjehJJSEQyAADFTTFBZCowDAADx42kWablKqRBkMnl8gXC8IsWnYsEAXz+YNl-JgUJhX1oqt0ZwuVwFNzujxeLAMIAASscscdcYqATA8XSaAzBlqBWKJTBqphsMY4uMjiAVOQIGCYpDofacW7FX56UVxanCiis9iURBiHFNm8upUNZ6ilKij6dfHjgagA这是在 TS Playground 里。

有什么方法可以告诉打字稿,当我映射一个元组时,它将返回一个同类的元组,而不仅仅是一个数组?我尝试非常明确地注释我的所有返回值等,但这并没有达到目的。

Typescript github 上有一个关于此的讨论:https://github.com/Microsoft/TypeScript/issues/11312 https://github.com/Microsoft/TypeScript/issues/11312

但我一直无法从中找到解决方案。


TypeScript 不会尝试在调用时保留元组长度map()。此功能是在微软/TypeScript#11312 https://github.com/Microsoft/TypeScript/issues/11312,实施于微软/TypeScript#11252 https://github.com/microsoft/TypeScript/pull/11252,并恢复到微软/TypeScript#16223 https://github.com/microsoft/TypeScript/pull/16223由于它对现实世界的代码造成的问题。看微软/TypeScript#29841 https://github.com/microsoft/TypeScript/issues/29841了解详情。

但如果你愿意,你可以合并到你自己的声明中 https://www.typescriptlang.org/docs/handbook/declaration-merging.html的签名Array.prototype.map(),以解释它保留元组长度的事实。这是一种方法:

interface Array<T> {
  map<U>(
    callbackfn: (value: T, index: number, array: T[]) => U,
    thisArg?: any
  ): { [K in keyof this]: U };
}

这使用多态性this https://www.typescriptlang.org/docs/handbook/advanced-types.html#polymorphic-this-types类型以及数组/元组映射类型 https://github.com/Microsoft/TypeScript/wiki/What%27s-new-in-TypeScript#mapped-types-on-tuples-and-arrays来表示变换。

那么你的代码可以写成如下:

function applyMove(board: Board): Board {
  return board.map(
    (row: Three, index: number) => (index === 0 ? applyMoveToRow(row) : row)
  );
}

function applyMoveToRow(row: Three): Three {
  return [2, row[1], row[2]];
}

并且不会有错误。请注意,我没有费心去处理Array.prototype.slice()。试图代表什么需要付出巨大的努力slice()对于元组类型,特别是因为没有真正的支持元组长度操作 https://github.com/microsoft/TypeScript/issues/26223...这意味着您可能需要一堆重载签名或其他类型的技巧来完成它。如果你只想使用slice()对于短数组,您也可以像我上面那样使用索引访问[2, row[1], row[2]]其中编译器does理解。

或者,如果您要将它用于较长的数组,但在代码中使用次数很少,您可能只想使用类型断言 https://www.typescriptlang.org/docs/handbook/basic-types.html#type-assertions告诉编译器你知道你在做什么。就此而言,如果你只是做map()少数情况下,您也可以在此处使用类型断言,而不是上面的重新声明map()的签名:

function applyMove(board: Board): Board {
  return board.map(
    (row: Three, index: number) => (index === 0 ? applyMoveToRow(row) : row)
  ) as Board; // assert here instead of redeclaring `map()` method signature
}

不管怎样,类型断言的类型安全性较低,但更简单,而声明合并更安全,但更复杂。

希望有帮助;祝你好运!

链接到代码 http://www.typescriptlang.org/play/#code/MYewdgzgLgBA+jAvDARKg3DA9FmBDVAIQBs8wBrFAKCqgE8AHAUxhLPKRnuZADN50NbiwDCTYsU5gArgFsARkwBOMAD6tSFQbUYsAKgAslTFsgDaYiQBoYl4jbsBdbcNYg8SgCaczh40xs-E0CjE2caUEhYAEswaKhovGJCdy8ALjcPb3MzOBsARhsAZkcbMyKbPJh80pgzQvhKx3CqWKhlXjxgFgBBJSU8OgAePQA+GABvKhgYWTwGIYBVUYAKaZmYYCTieS7yXjAMlYA3JOkmDL0bWM8mAA8MmQVlGw8BukuzRwBKJHHFqzrGZQAzRCB9ADmAH4MmQ6OtvhkJnUANIwWIwchMOh8LigiCODKLGAAX0EJJovGkYGACXA+AYDGIdAAsiBjkwVvJUp4MiksojMl5JutjFBpEowDBuVkAHRzBhrDYwFZKEAAd0uoQC6LAtweMCeiiUv0Q4xWN3uSEQyAADDAoQymaz2Uw9CAAEoa1Ua34ZNXq74I8mU6m06L0+bOtkc91e9U+zUwIJMQUpkUzMUSqVmABMNgD9VqhdzzRDVCAA

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在打字稿中将 array.map 与元组一起使用? 的相关文章

随机推荐

  • Cx 冻结错误 - Python 34

    我有一个 Cx Freeze 安装文件 我正在尝试使其工作 令人非常沮丧的是used适当冷冻 但是现在我收到以下错误 编辑 显示的错误不是通过控制台的 Python 异常 而是尝试启动通过冻结生成的结果 exe 文件时的崩溃报告 文件 no
  • 为什么在 while 循环中使用 itrerator 对象时需要进行类型转换? [复制]

    这个问题在这里已经有答案了 我现在正在学习java 在编写遍历代码时ArrayList using Iterator在使用迭代器的对象之前 我必须使用类名next 功能 有人能帮我解决这个问题吗 import java util publi
  • 使用“在模型中保存起始值”选项来帮助 Dymola 中的收敛

    I build a model in dymola Even though there are some errors during the initialization process but the calculation succee
  • Python 文档字符串模板化

    为什么动态格式化文档字符串不起作用 是否有可接受的解决方法来执行此操作在函数定义时 gt gt gt DEFAULT BAR moe s tavern gt gt gt def foo bar DEFAULT BAR hello this
  • IONIC 键盘隐藏在输入焦点上

    我正在编写一个 Ionic 应用程序 该应用程序将用于医疗保健领域的物流目的 用于此应用程序的设备具有内置条形码扫描仪并在 android 4 1 1 上运行 该扫描仪在输入字段中输入数据 并通过按 输入 键提交数据 由于扫描仪在某些情况下
  • 将本地存储从 Cordova 应用迁移到 Android 应用

    我们在 Playstore 中有一个使用 Cordova 开发的应用程序 现在我们已经在原生 Android 中重建了整个应用程序 现在我们希望在不注销的情况下将用户从以前的应用程序升级到新应用程序 为此 如何将Cordova window
  • 根据累计和和组创建新组

    我希望根据两个条件创建一个新组 我希望在 Value 的累计总和达到 10 之前将所有案例分组在一起 并且我希望在每个人中完成此操作 我已经设法让它分别适用于每个条件 但不能同时使用 for 循环和 dplyr 但是 我需要同时应用这两个条
  • 如何使用 IntelliJ 将外部库的源代码和 javadoc 添加到 gradle?

    我已经使用 IntelliJ 和 Gradle 建立了一个 Java 项目 我的根项目中有一个 build gradle 文件 我可以编译并运行我的应用程序 然而 我正在使用一个Java 库 它附带了源代码和javadoc zip 文件 如
  • 如何删除 div 和页面顶部之间的空间?

    这可能已经被问过一百万零一次了 但如果有人能向我解释 div 的行为 我将不胜感激 我有一个容器 div 我将其对齐在页面的中心 页面的顶部和顶部之间有一个间隙 我希望它与页面顶部齐平 我假设有某种我需要删除的边距或填充 但我无法想象它可能
  • OSX Mac App Store:如何安装守护进程 shell 脚本

    我想为 Mac App Store 编写一个涉及安装守护程序的应用程序 守护进程可以是一个非常简单的 Hello World shell 脚本 可以是 Bourne shell 或 Python 它应该在每次机器启动时自动运行 我尝试使用安
  • 如何在谷歌应用程序引擎中的留言簿中的每个帖子下添加日期和时间

    这是代码 import cgi import datetime import wsgiref handlers from google appengine ext import db from google appengine api im
  • 单击按钮时一个片段到另一个片段

    我已经学会了如何在单击按钮时将片段活动从一个更改为另一个 所有都是片段活动 但现在我遇到了同一片段上多个按钮的问题 只有第一个按钮 id 有效 我有多个按钮 每个按钮都有不同的片段活动 需要帮忙 package com test fragm
  • 将特定标头添加到 bitbake wget fetcher

    我需要设置一个特定的标头以使用以下命令从资源中获取存档wgetfetcher 类似于 wget header PRIVATE ACCESS TOKEN blablablablabla https some resource 如何使用该获取器
  • 如何在 iOS Swift 中将数据数组回调到另一个 viewController

    在createCardVC中 我使用carbonKit库来显示标签栏 最初 使用静态数据加载的数据数组 但现在我尝试使用来自 webView javascript postMessage 的数据数组 当 createCardVC 加载时 第
  • C++11 递归可变参数模板

    我想了解递归可变参数模板是如何工作的 include
  • Java 中的“快速”整数幂

    简短回答 糟糕的基准测试方法 你可能认为我现在已经明白了 该问题被表述为 找到一种快速计算x y的方法 其中x和y是正整数 典型的 快速 算法如下所示 public long fastPower int x int y Replaced m
  • 并发修改异常[重复]

    这个问题在这里已经有答案了 我有一小段代码 它给了我并发修改异常 我无法理解为什么我不断收到它 即使我没有看到任何并发修改正在进行 import java util public class SomeClass public static
  • SQL Server 和 Firebase/PouchDB 同步

    我正在构建一个 Web 应用程序 客户端需要在离线状态下通过浏览器访问数据存储 我正在考虑使用 Firebase 或 PouchDB 数据库在应用程序内实现此目的 但是 对于后端 我使用 SQL Server 我可以将 Firebase P
  • HTML 或 CSS 中的“父级”是什么?

    我被介绍到以下代码 div Here is span a span element span which is blue as span elements are set to be div div class extra style co
  • 如何在打字稿中将 array.map 与元组一起使用?

    每当我使用array map对于元组 Typescript 将其推断为通用数组 例如 以下是简单 3x3 数独游戏的一些片段 const a Blank type Blank typeof type Cell number Blank ty