任意泛型的 Typescript 映射

2024-03-20

我试图定义两种类型,它们应该类似于:

export type IQuery<P, U>  = {
  request: string;
  params: (props: P, upsteam?: U) => object;
  key: (props: P, upstream?: U) => string;
  forceRequest: boolean;
  depends?: QueryMap
}

export type QueryMap = {
  [k: string]: IQuery
};

我试图表达的限制是params and key它们的两个参数具有相同的类型,并且 QueryMap 只是从字符串到任意值的映射IQuery(类型是什么并不重要)。编译器在这里抱怨,因为它想要指定一个类型IQuery,但重点是每个IQuery地图中的内容应独立参数化。有没有办法用打字稿表达这一点?

此外,如果可能的话,我想获得有关上游形状的信息/保证QueryMaps 存在于IQuery当我迭代这棵树时。


The simplest你可以做的是:

export type QueryMap = {
  [k: string]: IQuery<any, any>
};

它并不完全类型安全,但与您想要表示的内容相差不远。如果您不想丢失 type 值的类型信息QueryMap,允许编译器推断更窄的类型并使用通用辅助函数来确保它是有效的QueryMap, 像这样:

const asQueryMap = <T extends QueryMap>(t: T) => t;

const queryMap = asQueryMap({
  foo: {
    request: "a",
    params(p: string, u?: number) { return {} },
    key(p: string, u?: number) { return "hey" },
    forceRequest: true
  }
});

价值queryMap.foo.params仍然被认为是一种接受string和一个可选的number,即使类型QueryMap['foo']['params'] isn't.

如果您指定某些不可分配给QueryMap你会得到一个错误:

const bad = asQueryMap({
  foo: {
    request: "a",
    params(p: string, u?: number) { return {} },
    key(p: string, u?: number) { return "hey" },
    forceRequest: true
  },
  bar: {
    request: 123,
    params(p: number, u?: string) {return {}},
    key(p: number, u?: string) {return "nope"},
    forceRequest: false
  }
}); // error! bar.request is a number

不完全类型安全的问题如下所示:

const notExactlySafe = asQueryMap({
  baz: {
    request: "a",
    params(p: number, u?: string) { return {} },
    key(p: string, u?: number) { return "hey" },
    forceRequest: true
  }
});

这是可以接受的,尽管没有一致的合理值P and U在这里工作(这就是当你使用时发生的情况any)。如果你需要更多地锁定它,你可以尝试让 TypeScript 推断出一组P and U值或警告您,如果它不能,但这并不简单。

为了完整起见,我将这样做......使用条件类型 https://github.com/Microsoft/TypeScript/wiki/What's-new-in-TypeScript#conditional-types推断P and U对于你的每个元素QueryMap通过检查params方法,然后验证key方法与之匹配。

const asSaferQueryMap = <T extends QueryMap>(
  t: T & { [K in keyof T]:
    T[K]['params'] extends (p: infer P, u?: infer U) => any ? (
      T[K] extends IQuery<P, U> ? T[K] : IQuery<P, U>
    ) : never
  }
): T => t;

现在以下内容仍然有效:

const queryMap = asSaferQueryMap({
  foo: {
    request: "a",
    params(p: string, u?: number) { return {} },
    key(p: string, u?: number) { return "hey" },
    forceRequest: true
  }
});

虽然现在这将是一个错误:

const notExactlySafe = asSaferQueryMap({
  baz: {
    request: "a",
    params(p: number, u?: string) { return {} },
    key(p: string, u?: number) { return "hey" },
    forceRequest: true
  }
}); // error, string is not assignable to number

这会稍微增加你的类型安全性,但代价是在类型中进行相当复杂的类型处理。asSaferQueryMap(),所以我不知道这是否值得。IQuery<any, any>对于大多数用途来说可能已经足够了。


好的,希望有帮助;祝你好运!

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

任意泛型的 Typescript 映射 的相关文章

随机推荐

  • 渐进式 Web 应用程序的预期启动体验是什么?

    测试渐进式 Web 应用程序 当我在飞行模式下启动应用程序时 我得到了意外的启动 启动体验 Android Chrome 从主屏幕体验启动 我看到一个白色的屏幕 然后是 离线恐龙 的短暂闪烁 然后应用程序成功启动 一切正常 启动时间比我预期
  • 如何自定义ARC-Welder的屏幕尺寸?

    我想将 ARC Welder chrome extension 的屏幕尺寸更改为 7 英寸屏幕 显示在我的电脑上 以在不同的屏幕尺寸上测试应用程序 这可以使用例如元数据输入来完成吗 类似于我最近问的问题 但我认为答案相同 似乎在外形规格方面
  • 如何正确处理Python中的可选功能

    我正在开发实现科学模型的 python 包 我想知道处理可选功能的最佳方法是什么 这是我想要的行为 如果无法导入某些可选依赖项 例如 在无头机器上绘制模块 我想在我的类中禁用使用这些模块的功能 警告用户如果他尝试使用它们以及所有这些 而不会
  • 如何在 Django 模型中轻松地将记录标记为已删除,而不是实际删除它们?

    我不想删除 Django 应用程序中的记录 而是只想将它们标记为 已删除 并将它们隐藏在我的活动查询中 我这样做的主要原因是为用户提供取消删除选项 以防他们意外删除记录 某些后端审计跟踪也可能需要这些记录 有很多外键关系 因此当我将记录标记
  • r facet_wrap 未与 geom_point 正确分组

    我正在与 R 中的facet wrap 作斗争 它应该很简单 但是facet 变量没有被拾取 这是我正在运行的 plot ggplot data item household descr count mapping aes x item h
  • 如何在 XSL 中“重用”代码

    我正在使用 XSLT 节点 我的问题是关于 XSL 的 我在互联网上进行了搜索 但我只找到了有关 XML 处理的信息以将其显示在网页上 我正在搜索的信息是如何在这种情况下 重用 某些代码 我的 XSL 是
  • jQuery colorbox onclose 更新父级

    可以为你们提供一些帮助 所以我使用 jQuery colorbox 并通过单击链接激活它 在颜色框中有一个带有一些复选框的表单 我想做的是在单击提交时将所选复选框的所有值获取到父级 并随后关闭颜色框 我不想刷新父窗口 它应该自动用内容填充
  • 警告:mysqli_connect():(HY000/1045):用户“用户名”@“localhost”的访问被拒绝(使用密码:YES)

    警告 mysqli connect HY000 1045 第 6 行 C Users xampp htdocs PHP Login Script config php 中的用户 用户名 localhost 使用密码 YES 访问被拒绝 即使
  • 名称 虚伪列表

    有人知道虚伪姓名的公开列表吗 名字的缩写形式 例如安东尼的托尼 罗斯玛丽的罗西或维多利亚的维姬 有一个 perl 模块可以在这里做到这一点 http metacpan org pod Lingua EN 昵称 http metacpan o
  • SVG 圆起点

    如何更改 svg 圆的起始点 使其从 0 点钟开始逐渐动画化 默认圆形 svg 从 3 点钟开始 我当前的圈子 悬停动画 timeline position fixed width 500px height 500px top 50 lef
  • Java Pair 类实现[关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 是否有经过验证的 Java Pair 类实现 我的意思是随时可用 被广泛接受和测试 可能是 Apache
  • jQuery Highcharts:使用下拉列表更改图表类型

    我正在尝试更改图表的值 如下所示
  • Git 推送不起作用错误“您必须使用个人访问令牌或 SSH 密钥”

    Git 抛出错误 C Program Files x86 Git bin git exe push u recurse submodules check progress origin refs heads dev civaplugin r
  • Android Holo 主题不包含多行微调器下拉项[重复]

    这个问题在这里已经有答案了 我最近刚刚在我的 Android 应用程序中实现了全息主题 执行此操作后 我拥有的任何下拉项长为多行的微调器都不会将文本换行为多行 每个下拉项目都保留在一行上并被截断为一定的长度 这是我的微调器下拉资源的 xml
  • 如何在 pyspark - dataframe 中将月份名称更改为不同的语言

    我正在尝试使用以下配置在 Databricks 上创建 日期 表 Get date range dateFrom dbutils widgets get date from dateTo dbutils widgets get date t
  • 在客户端计算机上安装 BCP 而不安装 SQL Server?

    我使用从数据库导出数据BCP实用程序 我想在客户端计算机上安装 bcp 我不想在客户端计算机上安装 SQL Server 2008 他们是否有可用于仅安装 bcp 的最小安装程序 这是一项紧急任务 提前致谢 您必须使用其中之一SQL Ser
  • 样式表中的单位“em”取决于什么。 CSS

    em根据屏幕尺寸调整尺寸 是的 但很困惑 em 取决于浏览器设置吗 哪些设置 或者 em 取决于屏幕分辨率 或者帮助它依赖什么以及从哪里可以更改这些元素以观察使用 em 时大小的差异 1em 等于当前字体大小 2em 表示当前字体大小的 2
  • 停止 JavaScript 中挂起的异步函数

    这里我有两个同时运行的 JS 异步函数 当一个结束 回调已运行 时 我想阻止另一个继续 但是 这是我的问题 我无法使用全局变量 然后 我想知道是否可以停止 JS 中的待处理函数或任何方法来解决我的问题 我将不胜感激任何答案 EDIT 一些澄
  • 修改后的 ClaimsPrincipal 无效

    我正在使用 ASP NET MVC Identity2 我添加了 名字 自定义ClaimPrincipal public async Task
  • 任意泛型的 Typescript 映射

    我试图定义两种类型 它们应该类似于 export type IQuery