根据值类型过滤键子列表的接口键

2024-01-06

Problem

给定一个被视为映射的 TypeScript 接口 (将唯一键类型与非唯一值类型相关),可以提取 映射到指定值类型的键类型?

作为一个具体的例子,从WindowEventMap in lib.dom.d.ts...

interface WindowEventMap 
    extends GlobalEventHandlersEventMap, WindowEventHandlersEventMap {
    "abort": UIEvent;
    "afterprint": Event;
    "beforeprint": Event;
    "beforeunload": BeforeUnloadEvent;
    "blur": FocusEvent;
    // ...
}

有一个内置运算符keyof获取所有密钥:

type FullKeyList = keyof WindowEventMap;
// gives: FullKeyList = "'abort' | 'afterprint' | 'beforeprint' | ..and 93 more"

是否有一些表达式可以仅过滤映射到值类型的键KeyboardEvent?:

// Goal:
type SubKeyList = SomeExpression<WindowEventMap, KeyboardEvent>;
// would give: SubKeyList = "'keyup' | 'keypress' | 'keydown'"

解决方案尝试

TypeScript 具有条件类型表达式:

T extends U ? X : Y

所以这是一个合理的尝试:

type Filter<K extends keyof M, V, M> = M[K] extends V ? K : never;

它过滤单个类型:

// Passes this test:
type FilteredExample1 = Filter<'keyup', KeyboardEvent, WindowEventMap>;
// gives FilteredExample1 = "'keyup'"

// Passes this test:
type FilteredExample2 = Filter<'blur', KeyboardEvent, WindowEventMap>;
// gives FilteredExample2 = "never"

它可以过滤类型的联合并返回一个新的联合吗?开始看起来不错:

// Passes this test:
type FilteredUnionExample1 = Filter<'keyup' | 'keydown', KeyboardEvent , WindowEventMap>;
// gives FilteredUnionExample1 = "'keyup' | 'keydown'"

但如果联盟的一名或多名成员失败,联盟就会失败:

// Fails this test:
type FilteredUnionExample2 = Filter<'keyup' | 'keydown' | 'blur', KeyboardEvent, WindowEventMap>;
// gives FilteredUnionExample2 = "never" (and not sub-union "'keyup' | 'keydown'")

// And so, it also fails the end-goal usage:
type AllKeysUnion = keyof WindowEventMap;
type FilteredUnionExample3 = Filter<AllKeysUnion, KeyboardEvent , WindowEventMap>;
// gives FilteredUnionExample3 = "never" (not sub-union "'keyup' | 'keypress' | 'keydown'")

这个问题有解决办法吗?


我通常称之为KeysMatching:

type KeysMatching<T, V> = {[K in keyof T]: T[K] extends V ? K : never}[keyof T];

type SubKeyList = KeysMatching<WindowEventMap, KeyboardEvent>
// type SubkeyList = "keydown" | "keypress" | "keyup"

Playground 代码链接 https://www.typescriptlang.org/play?jsx=3#code/C4TwDgpgBA0hIGcCyBDYBjAFgSwHYHMAeAFQBooA1APigF4oBvAbRijygGt4B7AMymIBdAFwCWgqBAAewCLgAmCSlAD8sKKNwQAbhABOAXyZcQfAYIDcAWABQt0JCgBlAK4AjOCAAy2BMDqw8MhoWHhEAOp48twA7gCiurjAqGDknm7cKHryCXLAVLYA9IVQDtCubiY+fgEARCbRMbi1UAA+UPXwYHoQCAgt7Z0gLmC1QA

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

根据值类型过滤键子列表的接口键 的相关文章

随机推荐

  • 检查 bash 中的空字符串

    下面的测试有什么区别吗 STRING exit 1 x STRING x exit 1 z STRING exit 1 不 它们都是一样的 但需要养成一些防守习惯 你应该引用 STRING in the z也有一个 如果您使用 u 选项运行
  • java 和 R 与 Rserve 的连接

    我有用于分析的java应用程序 需要安装R 我的系统中还安装了 R 并且安装了 Rserve 库 但是当我尝试在 R 控制台中实现命令 Rserve 时 出现以下错误 SOCK ERROR 绑定错误 98 地址已在使用中 我已经安装了我的
  • virtualenv:在 Mac 上使用 Pip 安装后找不到命令[重复]

    这个问题在这里已经有答案了 我正在尝试在我的 Mac 上安装 VirtualEnv 我已经用brew安装了Python和Pip 运行后 pip 安装虚拟环境 当我尝试使用它时 我得到 bash virtualenv command not
  • 如何在fork()创建的进程之间共享内存?

    在fork子进程中 如果我们修改一个全局变量 它不会在主程序中改变 有没有办法更改子叉中的全局变量 include
  • stage.addChild 和分层

    我有一个简单的功能 当您单击按钮时 会随机将影片剪辑添加到舞台上x and y位置 我遇到的问题是新的影片剪辑最终会掩盖按钮 我尝试将新创建的影片剪辑的 z 索引更改为低于按钮的 z 索引 但这并不能解决问题 如何阻止新的影片剪辑覆盖已经存
  • Ruby:删除字符串开头的空白字符

    编辑 我通过使用解决了这个问题strip to 删除前导和尾随空格 如我在该视频中所示 https www youtube com watch v Ef hGfJGt3U 然后 我通过迭代并添加空格来恢复数组每个字符串末尾的空格 这个问题与
  • C++ 对两个配对整数数组的“百分比”进行排序

    我有一个程序 有 2 个 配对 整数数组 newNumerator 和 newDenominator 其中都有 9 个整数 我编写了一个函数 按升序对它们进行排序 但是我不确定它是否有效 因为我还没有成功编译它 我在打字方面也遇到了一些问题
  • 使用静态产品测试计费会返回 SERVICE_DISCONNECTED

    我正在将我的应用程序中的应用程序内结算从版本3 http www androiddocs com google play billing billing integrate html to 较新的代码 https developer and
  • Vue Router:如何将参数转换为整数而不是字符串?

    当我使用浏览器字段输入 URL 时 参数将转换为字符串 而不是整数 例如 user 1回报 id 1 然而 当使用时this route push 参数正确地转换为整数 id 1 这种行为是故意的吗 如果没有 我该如何解决 您必须自己处理任
  • 请求运行时位置权限时

    目前 当第一次启动我的应用程序时请求运行时权限时 它会提示用户使用他们的位置 如果您单击 是 它不会像应有的那样启用位置 但如果我重新启动该应用程序 它就会启用该位置 关于在哪里可以让它在首次启动时启用位置有什么建议吗 代码的第一部分在 O
  • AesManaged 和 RijndaelManaged

    我目前正在开发一个连接到旧 Web 服务的 Silverlight 应用程序 我们的旧 Web 服务使用 silverlight 不支持的加密工具 最后 我们决定使用 AesManaged 进行加密 但是 我们的网络服务不支持 AesMan
  • 检测 Entity Framework Core 中的延迟加载

    Entity Framework Core 3 1 2 我已启用UseLazyLoadingProxies on my DbContext以确保数据完整性 但如果使用它 我想在开发过程中抛出异常 如何在每次 EF Core 延迟加载关系时执
  • 在 EC2 上的 Virtualenv 中运行 Django -- ImportError:没有名为 django.core.management 的模块

    我在 git 存储库中本地开发了一个 django 应用程序 我为该项目启动了一个 EC2 实例 并设置了一个包含 我认为是 正确的包 依赖项的 virtualenv 然后我继续将我的存储库克隆到 virtualenv 中 现在 我遇到了困
  • 私有方法和属性的 ReSharper C# 命名风格

    我喜欢将私有方法 属性和事件的首字母设为小写 将公共方法 属性和事件的首字母设为大写 但是 在 ReSharper 7 1 中 C 命名样式下只有一个选项适用all方法 属性和事件 告诉 ReSharper 使用不同约定的最佳方法是什么pr
  • 无序映射与向量

    我正在构建一个小型 2D 游戏引擎 现在我需要存储游戏对象的原型 所有类型的信息 我猜一个容器最多有几千个元素 所有元素都有唯一的键 并且在第一次加载后不会删除或添加任何元素 键值是一个字符串 各种线程将运行 我需要向每个人发送一个密钥 或
  • 我怎么知道是否是require_once?

    我有两个文件 1 索引 php 2 main php 索引 php拨电至main php by 我怎么知道从main php当它执行时 if 索引 php调用他或同一用户独立执行它 如果是 require once 我应该在主 php 中询
  • 如何在 phpunit 中引用外部数据提供者?

    我正在尝试使用 PHPUnit 中的通用数据提供程序运行一些测试 参见下面的测试 namespace AppBundle Tests Controller use Symfony Bundle FrameworkBundle Test We
  • 使用数据框索引数据的 pandas 数据透视表

    我想从 pandas 数据框创建一个数据透视表 使用 dataframe pivot 并且不仅包括数据帧列 还包括数据帧索引中的数据 找不到任何说明如何执行此操作的文档 有小费吗 Use reset index使索引成为一列 In 45 d
  • 在 Android 中为图像视图添加缩放功能

    我想在我的 Android 应用程序中添加缩放功能 我已经尝试过这段代码 但它只是在图像中间放大和缩小 我想对整个图像应用缩放 在同一张图像中 我可以在图像的某些区域放置一个按钮吗 import android content Contex
  • 根据值类型过滤键子列表的接口键

    Problem 给定一个被视为映射的 TypeScript 接口 将唯一键类型与非唯一值类型相关 可以提取 映射到指定值类型的键类型 作为一个具体的例子 从WindowEventMap in lib dom d ts interface W