Typescript 实现接受多种类型输入的通用函数

2024-03-05

出于抽象目的,我需要实现一个接受不同类型输入的函数。

type ContentA = string

type ContentB = number

type InputA = {
 name: 'method_a'
 content: ContentA
}

type InputB = {
 name: 'method_b'
 content: ContentB
}

type Input = InputA | InputB

每个输入都需要不同的方法:

const my_methods = {
 method_a: (content:ContentA) => {
  // ...
 },
 method_b: (content:ContentB) => {
  // ...
 }
}

现在我需要实现一个接受所有输入的通用函数,这是因为输入类型可能很多,现在只有 2 个,但在我的实际应用程序中它们大约是 16 个。

我想要一个像这样的实现,但是它导致我出现编译错误:

function foo(input:Input){
 return my_methods[input.name](input.content);
                             // ^
                             // | Argument of type 'string | number' is not  
                             // | assignable to parameter of type 'never'.
                             // | Type 'string' is not assignable to type 'never'.
}

有没有办法让 Typescript 推断出,因为我正在使用input.name那么该方法的参数是正确的 - 因为它们总是匹配input.name and input.content?

游乐场链接 https://www.typescriptlang.org/play?#code/C4TwDgpgBAwg9gO2BJBBKBeKBnYAnASwQHMAoU0SWRZJAIUygQFcBbAIwj3MugEkEYZsHRYA3qSYBDVhABcUAOSzgACzgATAPpTFkgMY0UwBfCTHUpAL49w-QcIbjJCGfKUr129nqiHzSKZG9Na2VAJCwIwRwugAPlAxwHTk-rhQrCBanprYjBIZEGqaOgoAFP60JmZVqACUmAB8UAVQAPRtUAB0PZJWADSSOd7llcZyNcZ0DRjNrR3dvVA2NqQAZswI+sAEiFBrcHBlRJFySXUFeEXMeAgZWcPYANonwl2usgC6xw7AXWNIOoAbmsQA


这是一个有趣的挑战,但我找到了一个足够好的解决方案,并且似乎可行。

我的想法是采用你最初的联合类型Input并将所有内容都变成泛型,因为缩小了受歧视的联合(基于您的name)实际上只适用于文字。

首先,让我们创建一个具有所有可能的类型name values:

type Names = Input["name"];

接下来,创建一个“查找”泛型类型,给定name作为类型参数,给你content类型。例如,ContentByName<"method_a"> is ContentA.

type ContentByName<TName extends Names> = {
  [i in Input as i["name"]]: i["content"];
}[TName];

这样,我们为您创建了一个特定的类型my_methods目的。这似乎让编译器足够清楚地知道名称和类型类型确实属于彼此:

type Methods = { [name in Names]: (content: ContentByName<name>) => void };

const my_methods: Methods = { // <-- added to your code here
  // ...
}

最后你的foo函数也需要是通用的,为此我们还需要创建一个通用版本Input type.

type InputByName<TName extends Names> = {
  name: TName;
  content: ContentByName<TName>;
};

function foo<TName extends Names>(input: InputByName<TName>) {  // <-- added
  //...
}

请注意,您可以愉快地使用普通的 ol' 调用此函数Input就像你以前做的那样。这是完全有效的:

function foo_old(input: Input) {
    return foo(input);
}

我们实际上并没有change有关类型的任何信息;我们只是帮助编译器推理它们。

这是游乐场链接与我的更改 https://www.typescriptlang.org/play?#code/C4TwDgpgBAwg9gO2BJBBKBeKBnYAnASwQHMBuAKHNElkWSQCFMoEBXAWwCMI8KrxoASQRhWwdFgDe5KCwCG7CAC4oAIkXAAFnAAmAfTmqKsgMZ0UwFfCQXUFAL59qQkWKZSZ8xSvUQtuvU4jTzMbJCtzRgcnAShhUWBmeLF0AB8412AGGJoAOQUIbCTMgG1VBALVAF0c6Gt6LJB8xQAeABVm6AgAD3odIs7sAD5maVkSgigiDISoOSKCMorFaqqVRdVQhuqHEo6CmspnKABZP21+0agS5ehpwbWoAAotiwiwxs6W26GASkwRgA3OAEHRQRyUUK4KDsEB6DQXbAqM7+S4eWQIgJyFQvSKWWgfVD-DAjMayKAAegpUAAdHTPPYADSeTH6Tg417hAkNBjE0meWRU2n02RM8gQ-g0ZKfArtTpQHp9AYFYajTy3FT7RTGKCc-H1CwMJqyrUQIbRSgAM1YCBMwAIiCglrgcDlBQVvRQl0GQyeRASKmlRq+pr+UDJeD8rDwCBhcNZ2AmmRptyqfuTet+DitNrtDtjzrgejgABsdOmAzMxP8ybJI8BowWXRXqw4gA.

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

Typescript 实现接受多种类型输入的通用函数 的相关文章

随机推荐

  • Appfabric WF4-WCF服务,如何在没有httpcontext的情况下检索codeactivity中的当前url?

    我开发了一个带有代码活动的 wf wcf 服务 我想在其中检索该服务的当前 URL 如果我禁用 appfabric 的持久性功能 我可以使用以下命令检索 URL HttpContext Current Request Url ToStrin
  • Swift - 协议作为按钮操作的目标类型

    我正在尝试创建 HeaderView 它是 UIView 的子类 它包含一个关闭按钮和一个标题标签 class HeaderView UIView private var titleLabel UILabel private var clo
  • 无法将 _InternalLinkedHashMap 转换为任何内容

    尽管我首先将其作为地图上传 但从 Firebase RealtimeDatabase 获取数据作为地图时遇到了一些问题 我看到的所有解决方案都是您应该将 snapshot value 转换为传入的数据类型 但对我来说没有任何迭代 我已经可以
  • 如何将 MongoDB 与 Solr 集成?

    我以前见过这个问题 但从未收到真正的答案 所以我想知道 有人可以指出我如何将 mongoDB 与 Solr 集成的正确方向吗 我正在寻找伪实时和最终的一致性 做过这件事的人可以透露一些信息吗 如果有帮助的话 我还将 PHP Zend 与 D
  • 如何使用 Rails 2.1 和 MySQL 定义 BigInt 主键?

    从 Rails 2 1 开始 如果您在迁移中定义一个新列 其类型设置为 integer 且 limit 设置为 5 或更多 则在 MySQL 数据库中实际创建的列将是 BigInt 类型 那很完美 但我不知道如何创建具有 BigInt 主键
  • 高级错误处理

    我最近摆了个姿势这个问题 https stackoverflow com questions 15295004 disregarding simple warnings errors in trycatch noredirect 1 com
  • 使用 Java 为 Blogger API 验证自己的 Google 帐户

    我想编写一个将本地文件发布到 Google Blogger 的机器人 我将是唯一使用此应用程序的人 因此我不需要设置用户友好的身份验证例程 我花了一个晚上尝试进行设置 但仍然在处理 OAuth 请求方面遇到困难 我创建了一个新的 Googl
  • 现代 OpenGL 相当于 glBegin/glEnd 的是什么

    我正在为 OpenGL 构建一个图形 API 它基于基本的调用绘制图形样式 基本上 不是将数据存储到 GPU 中 并使用它的句柄调用它 而是提供信息来绘制每次更新应该绘制的内容 我知道它很慢 但它很简单 而且适用于非性能关键型应用程序 无论
  • 正则表达式:如何匹配不仅仅是数字的字符串

    是否可以编写一个正则表达式来匹配所有不匹配的字符串only包含数字 如果我们有这些字符串 abc a4c 4bc ab4 123 它应该匹配第一个 但不是最后一个 我尝试在 RegexBuddy 中摆弄前瞻之类的东西 但我似乎无法弄清楚 d
  • 如何在关系数据库中建模多语言实体

    如果我们要开发一个多语言应用程序 我们应该将翻译存储在资源文件 or the database 假设我们选择在数据库中进行 是否有一种标准方法来建模多语言实体关系模型 1 一张大翻译表 我们可以将所有翻译存储在一张表中并使用语言中立键为属性
  • Flexbox行:不根据内容增长? [复制]

    这个问题在这里已经有答案了 我有以下结构 我想了解为什么我的行不随其内部内容增长 row border solid red display flex flex direction row cell border solid green fl
  • 在 Maps API 浏览器上设置 HTTP Referrer 会导致 403 错误

    我对 HTTP Referrer 设置如何在 Google Maps API 浏览器密钥上工作感到困惑 我正在构建一个网页 以编程方式从 Google 地图请求图像 主要是 Google 地图街景图像 API 但也从 Javascript
  • spring-boot-starter-web 和 spring-boot-starter-webflux 不能一起工作吗?

    当我开始学习spring webflux 我对这个组件有疑问 我建立了一个简单的项目 使用maven来管理它 我添加了相关的依赖项spring boot starter web and spring boot starter webflux
  • Rufus 调度程序未登录生产环境

    我的 Rails 应用程序在初始化程序中使用 rufus scheduler 启动一个进程 这是初始化程序代码的精简版本 config logger isn t available here so we have to grab it fr
  • React 将 JQuery 代码应用于组件内的元素

    我有一个正在使用 React 的应用程序 我现在遇到一个问题 我正在尝试实施bootstrap 所见即所得 bootstrap3 所见即所得 https github com bootstrap wysiwyg bootstrap3 wys
  • 自动删除SQS队列

    有没有办法完全自动删除 SQS 队列 我有一个解决方案 其中服务器在启动时创建 SQS 并订阅 SNS 主题 然而 可能存在服务器崩溃且无法恢复的情况 在这种情况下 我会用另一台服务器替换该服务器 该服务器会在启动时创建自己的队列 现在之前
  • 对多个区域使用 Matcher.appendReplacement()

    java Matcher appendReplacement 方法 带有appendTail 应该让我将源文本转换为结果文本 同时替换所有出现的模式 伪语言的算法类似于 while Matcher find call Matcher app
  • 用于检查大网址列表中损坏链接的 Python 工具

    我有一个正在生产的搜索引擎 为大约 700 000 个网址提供服务 爬行是使用 Scrapy 完成的 所有蜘蛛程序都使用 DeltaFetch 进行调度 以便获取每日新链接 我面临的困难是处理损坏的链接 我很难找到一种定期扫描和删除损坏链接
  • 是否可以将 HTML/CSS 布局与 GWT 逻辑完全分离?

    我想让我们的 Web 开发人员继续使用纯 HTML 工作 并让开发人员编写 GWT 仅 Java 代码来编写其余的业务逻辑 有可能吗 有人尝试过在 GWT 环境中与 Web 开发人员一起工作吗 如何将 Web 开发人员纳入 GWT 开发流程
  • Typescript 实现接受多种类型输入的通用函数

    出于抽象目的 我需要实现一个接受不同类型输入的函数 type ContentA string type ContentB number type InputA name method a content ContentA type Inpu