Typescript:通用到特定类型

2024-05-20

我有一个通用类型

type GenericType = {
  [key: string]: {
    prop1: string,
    prop2?: string,
    prop3?: number,
  },
};

我使用通用类型来帮助构建/类型检查我创建的新对象。

const Obj1: GenericType = {
  key1: {
    prop1: "hi",
  },
  key2: {
    prop1: "bye",
    prop2: "sup",
  },
};

有用。但是,当我使用新对象时,vscode / typescript 不显示的键或道具Obj1无需删除GenericType从中。我也可以“扩展”类型,但这是代码重复。

Obj1.???

有没有办法保留 GenericType,同时可以从我创建的新对象中访问更具体的道具?


Update 1

我希望 vscode / typescript 能够显示/验证

Obj1.key1.prop1
Obj1.key2.prop1

和错误如果

Obj1.key1.prop2
Obj1.key2.prop3
Obj1.key2.prop321

我看到了你想要的用例GenericType可以使用任何类型的字符串作为键,但仍然希望在声明它们时准确确定这些键的值是什么。

在这种情况下,您可以使用Record https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkeystype类型来限制允许的键Obj1仅限您指定的键。

type GenericType<K extends string> = Record<K, {
  prop1: string,
  prop2?: string,
  prop3?: number,
}>

那么定义的时候Obj1您可以通过将允许的键的并集设置为第一个类型参数来指定允许的键。

const Obj1: GenericType<"key1" | "key2"> = {
  key1: {
    prop1: "hi",
  },
  key2: {
    prop1: "bye",
    prop2: "sup",
  },
};

TypeScript 现在可以让您访问两者key1 and key2具有完整的类型安全性。

Obj1.key1
// (property) key1: {
//     prop1: string;
//     prop2?: string | undefined;
//     prop3?: number | undefined;
// }

EDIT

根据OP的评论,听起来他宁愿不指定所有键名称,或者必须手动检查可选字段是否存在。

我能想到的最好方法是这样做,同时仍然确保您声明的对象与对象的约束相匹配GenericType接口是做类似下面的事情。

首先你需要这个实用程序类型:

type Constraint<T> = T extends Record<string, {
  prop1: string,
  prop2?: string,
  prop3?: number,
}> ? T : never

这将返回never if T不符合约束条件或者只是T否则。

现在你声明你真正想要的普通对象。没有类型注释。

const CorrectObj = {
  key1: {
    prop1: "hi",
  },
  key2: {
    prop1: "bye",
    prop2: "sup",
  },
};

然后将此对象文字分配给另一个变量,但声明新变量的类型必须为Constraint<typeof CorrectObj>

const CheckedObj: Constraint<typeof CorrectObj> = CorrectObj

If CorrectObj则匹配约束CheckedObj将是一个简单的副本CorrectObj所有字段均可用。

如果对象文字与约束不匹配,那么在尝试将 CheckedBadObj 分配给文字时,您将收到类型错误:

const BadObj = {
  key1: {
    progfdgp1: "hi",
  },
  key2: {
    prop1: "bye",
    prdfgop2: "sup",
  },
};

const CheckedBadObj: Constraint<typeof BadObj> = BadObj
//    ^^^^^^^^^^^^^
// Type '{ key1: { progfdgp1: string; }; key2: { prop1: string; prdfgop2: string; }; }' is not assignable to type 'never'. (2322)

解释是Constraint<T> when T不匹配的是never,但你仍然试图分配一个非never价值CheckedBadObj,导致类型冲突!

这在声明每个对象文字的两个实例时涉及到一些重复,但这是唯一的方法

  1. 让 TypeScript 知道exactly对象上存在哪些字段,包括所有子对象,同时仍然
  2. 检查“通用”类型的值 符合你的限制

您可以在操场 https://www.typescriptlang.org/play?#code/C4TwDgpgBAwg9gOwM7AE4EMCWDgB4AqAfFALxT5QQAewECAJklAEoQDGcq9uKq2A5gBooAbwBQUKGFRwwARgBcUXgMESpMsACYA-EpUIh66bIDMeqAgCuAWwBGEVGoC%20xHeShKEEAG6OxARzIwLCcqOzAAPJ2AFakouoA1hAgigmSkibySgBEABaYOWqSzsVQySBaSuIZGrJpOXYgEEXqmZpVUDlIVmCtJS4A3IGIKLB57Mn00TFp8MEY2HigkHAAZqGo4WxRscRk8FsRMyPBUABC6NOx8TXlKWl37XD8a-T82V0F-VClSSmdJ51T6NZo-dr0Nb8WSdbq9H5-ZzDMRBMYwCZsKaXa4xJTzXhYHC4FYQdYXK4zfbknFAA.

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

Typescript:通用到特定类型 的相关文章

随机推荐

  • RSpec 无法从 Factorygirl 中找到工厂

    我将在 Rails3 项目中将 RSpec 与 Factory Girl 一起使用 我已经安装了 Factory Girl 但它找不到工厂我有这个错误 Failure Error Factory build user should be v
  • 使用 VBA 将 Excel 电子表格中嵌入的 Word 文档保存到磁盘

    我们有一个 Excel 电子表格 当前使用存储在公司 LAN 上的 Word 模板生成报告 这对于内部用户来说效果很好 但对于没有连接到 LAN 的任何人来说就不行了 例如 笔记本电脑用户 管理层不希望将模板作为单独的文件分发给外部用户 而
  • Process.Close() 不会终止创建的进程,c#

    我编写了一个 C 应用程序 它使用System Diagnostics Process类来创建进程 使用 Process P1 new Process P1 FileName myexe exe 和其他适当的设置 我已将其链接到一个运行大约
  • 如何跟踪推文按钮点击次数?

    我想通过 Google Analytics 跟踪推文按钮点击 但推文按钮是一个包含来自另一个域的内容的 iframe 是否有一些技巧可以为推文按钮点击添加回调 或者 您可以简单地将事件添加到您的 div 中 然后等待该 div 被单击 例如
  • 如何设计 RESTful 搜索/过滤? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我目前正在 PHP 中设计和实现 RESTful API 然而 我并没有成功地实现我最初的设计 GET users list of users
  • Android 视频捕获示例应用程序

    Android 中有用于视频捕获的独立示例代码吗 以下是我为学生提供的内容 摄像机源 http itp nyu edu sve204 mobilemedia spring10 Camcorder zip
  • Google Apps 脚本 - 是否可以仅通过 Google Apps 脚本更改表格中的某些单元格?

    我在 Google SpreadSheet 中制作了一个目录 我的电子表格有一个表格 用户可以在其中添加信息 该表是通过从数据库表获取数据的脚本动态创建的 用户可以编辑表中的某些单元格 然后单击按钮将更改保存回数据库表中 我想限制他可以手动
  • iOS中的performSelector有什么用

    的作用是什么执行选择器 比较 self btnClicked and self performSelector selector btnClicked void btnClicked NSLog Method Called 两者都对我来说工
  • 在 IIS 7 托管环境中获取 URL 路由让我绞尽脑汁:ASP.NET

    我正在尝试使用 ASP NET URL 路由来实现系统 Web 路由 这似乎在我的本地主机上工作正常 但是当我上线时 我收到 IIS 7 的 404 错误 找不到文件 仅供参考 托管使用 Windows Server 2008 IIS7 我
  • 如何减少 Bitbucket 上的 git repo 大小?

    我的问题摘要 在我向两个现有文件添加了几百个字节后 我在 Bitbucket 上的一个私人存储库的大小突然增加了一倍多 该存储库现在超过 2GB 这导致 Bitbucket 将其置于只读模式 因为它处于只读模式 所以我无法推送会减少存储库大
  • WinDbg:dd <地址> L <长度> 的范围限制

    WinDbg 对 d 命令系列有范围限制 根据文档 限制为 256 MB 使用 L 可以绕过此限制 句法 L Size 带问号 的意思与LSize相同 只是L 大小删除了调试器的自动范围限制 通常 有 范围限制为 256 MB 因为更大的范
  • 在 nitrousio 中安装 python 包

    我刚刚开始尝试使用 Nitrous io 我用 python 做了一个盒子 并尝试使用 pip 安装一个名为 praw 的 python 包 它可以很好地下载所有信息 但在运行安装脚本时 我收到一条错误消息 指出由于 usr 目录中的权限限
  • 我的 .NET 库列表中缺少 System.Windows.Data

    您好 我想使用 System Windows Data IValueConverter 但是当我尝试在 VS2010 中添加对 System Windows Data 的引用时 我只看到 System Windows Forms 和 Sys
  • 如何使用 .Net Core 和 VSCode 在调试模式下执行测试?

    如何使用 Net Core 和 VSCode 在调试模式下执行测试 我当前正在命令行上运行以下命令 dotnet Test 但是 这不是在调试模式下执行测试 我要附加调试器吗 如果是这样 怎么办 如有必要 请将测试项目转换为控制台应用程序
  • 为什么 QGraphicsWidget 的选择边框在 QGraphicsScene 中不可见?

    我已经通过一个小部件添加到图形场景 QGraphicSscene QGraphicsProxyWidget 问题是 当我选择该项目时 它被选中 但选择边框不可见 这是代码 QDial dial new QDial Widget dial g
  • 显示 master 之前/之后有多少提交分支的别名

    新的 Bitbucket Branches 页面非常棒 它显示每个分支领先 落后于 master 的提交数量 是否有显示相同信息的 Git 别名 信息应显示 分店名称 上次更新是什么时候 其背后有多少提交 有多少提交领先于 master 看
  • 在同一浏览器中打开新选项卡时如何关闭选项卡?

    我在浏览器选项卡中打开了一个网站 现在 当我从此网站打开新选项卡时 我想关闭该浏览器中的第一个选项卡 使用这个脚本
  • 没有名为“PIL”的模块

    当我尝试时遇到错误 from PIL import Image ImageFilter 在 Python 文件中我收到一条错误消息ModuleNotFoundError No module named PIL 到目前为止 我已经尝试卸载 重
  • Python - 应该直接在 Python 3.x 中启动一个新项目吗?

    对于长期 数年 项目 您可以推荐什么 Python 版本 应该使用 2 6 还是 3 x 已经稳定了 仅需要标准库 更新 根据下面的答案 Python 3 x 仍然存在严重错误 另请参阅Python 的错误列表 http bugs pyth
  • Typescript:通用到特定类型

    我有一个通用类型 type GenericType key string prop1 string prop2 string prop3 number 我使用通用类型来帮助构建 类型检查我创建的新对象 const Obj1 GenericT