Typescript:对象和基元之间的 keyof typeof union 始终是 never

2023-11-22

首先,我的问题的一些背景信息:我有一个项目,在其中我通过 Socket.IO 接收一个对象,因此我没有关于它的类型信息。此外,它是一种相当复杂的类型,因此需要进行大量检查以确保接收到的数据良好。

问题是我需要访问由接收到的对象中的字符串指定的本地对象的属性。这对于第一个维度来说效果很好,因为我可以将任何类型的属性说明符转换为keyof typeof无论我想访问什么(例如this.property[<keyof typeof this.property> data.property]).

结果变量的类型显然是一个相当冗长的联合类型(联合所有属性的所有类型)this.property有)。一旦这些属性之一属于非原始类型keyof typeof subproperty被推断为never.

通过之前所做的检查,我可以保证该属性存在,并且我 99% 确信代码一旦编译就会运行。只是编译器在抱怨。

下面是一些非常简单的代码,可以重现此行为以及观察到的和预期的类型。

const str = 'hi';
const obj = {};
const complexObj = {
    name: 'complexObject',
    innerObj: {
        name: 'InnerObject',
    },
};

let strUnion: typeof str | string;              // type: string
let objUnion: typeof obj | string;              // type: string | {}
let complexUnion: typeof complexObj | string;   // type: string | { ... as expected ... }

let strTyped: keyof typeof str;                 // type: number | "toString" | "charAt" | ...
let objTyped: keyof typeof obj;                 // type: never (which makes sense as there are no keys)
let complexObjTyped: keyof typeof complexObj;   // type: "name" | "innerObject"

let strUnionTyped: keyof typeof strUnion;       // type: number | "toString" | ...
let objUnionTyped: keyof typeof objUnion;       // type: never (expected: number | "toString" | ... (same as string))
let complexUnionTyped: keyof typeof complexUnion;   // type: never (expected: "name" | "innerObject" | number | "toString" | ... and all the rest of the string properties ...)
let manuallyComplexUnionTyped: keyof string | { name: string, innerObj: { name: string }};  // type: number | "toString" | ... (works as expected)

这是 TypeScript(版本 3)的已知限制还是我在这里遗漏了一些东西?


如果您有联合,则只能访问公共属性。keyof将为您提供某种类型的可公开访问的密钥。

For strUnionTyped之间的并集string和字符串文字类型'hi'结果类型将具有与 string 相同的属性,因为联合中的两种类型具有与 string 相同的键。

For objUnionTyped and complexUnionTyped联合体没有公共键,因此结果将是never

For manuallyComplexUnionTyped你得到的钥匙string,因为你写的实际上是(keyof string) | { name: string, innerObj: { name: string }} not keyof (string | { name: string, innerObj: { name: string }})所以你得到了钥匙string在与您指定的对象类型的联合中。

要获取联合体所有成员的键,您可以使用条件类型:

type AllUnionMemberKeys<T> = T extends any ? keyof T : never;
let objUnionTyped: AllUnionMemberKeys<typeof objUnion>;
let complexUnionTyped: AllUnionMemberKeys<typeof complexUnion>;

Edit

条件类型有助于获取所有联合成员的键的原因是因为条件类型分发超过裸类型参数。所以在我们的例子中

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

Typescript:对象和基元之间的 keyof typeof union 始终是 never 的相关文章

随机推荐

  • 如何从 Tkinter 窗口立即停止 Python 进程?

    我有一个 Python GUI 用来测试我工作的各个方面 目前我有一个 停止 按钮 可以在每个测试结束时终止进程 可以设置多个测试同时运行 但是 有些测试需要很长时间才能运行 如果我需要停止测试 我希望它立即停止 我的想法是使用 impor
  • scrapy使用CrawlerProcess.crawl()从脚本将custom_settings传递给spider

    我正在尝试通过脚本以编程方式调用蜘蛛 我无法使用 CrawlerProcess 通过构造函数覆盖设置 让我用默认的蜘蛛来说明这一点 用于从官方 scrapy 网站抓取引号 最后一个代码片段位于官方 scrapy 引用示例蜘蛛 class Q
  • 导出类的公共属性在 TypeScript 中使用私有类型错误

    C dev OpenCMS Website Frontend Scripts libs sinnovations gt tsc sinnovations listv iewbase ts module amd C dev OpenCMS W
  • 如何将 Enter 键绑定到 tkinter 按钮

    我正在尝试绑定回车键 with a button 在下面的代码中 我试图从条目小部件中获取条目 当按钮bt被按下 它调用enter 获取条目的方法 我还希望通过按回车键 我没有得到想要的结果 在条目小部件中输入的值不会被读取 并且enter
  • 如何在 Kubernetes 中从工作节点找到主节点

    我需要知道我当前的工作节点连接到哪个主节点 我可以通过在主节点中输入 kubectl getnodes 命令来查看工作节点 但我需要从工作节点本身找到主节点 简单来说 kubernetes集群中如何从worker节点找到master节点 您
  • 如何记录 Spring Data JPA 存储库方法的执行时间?

    我有简单的 Spring Data JPA 存储库 public interface UserRepository extends JpaRepository
  • C# 中的匿名类型

    x is compiled as an int var x 10 y is compiled as a string var y Hello z is compiled as int var z new 0 1 2 but ano is c
  • Rails Mongoid 无法进行身份验证 - 失败并出现错误 13:“未授权对 my_db.my_collection 进行查询”

    这个问题据说最新版本的Moped已经解决了 但我仍然遇到这种情况 我有一个 Rails 4 2 应用程序Mongoid 为 MongoDB 数据库创建了一个用户读写 and dbOwner角色 并设置授权 真 in the mong con
  • MPAndroidChart LineChart:使用日期而不是字符串作为 X 轴

    MPAndroid图表折线图默认情况下接受 X 轴字符串 有没有办法将日期设置为 X 轴的数据类型 仅将日期转换为字符串的问题是图表可能会根据数据点而倾斜 例如 如果我在 1 月份有一个数据条目 在 6 月份有 10 个数据条目 则默认情况
  • Shiny - 在输出中使用观察函数调用的结果

    我有一个闪亮的应用程序 其中基于所选选项 列 数据集动态重新计算 重新计算的结果用于向用户显示另一组选项并创建绘图 目前我正在使用observe 读取用户选择 重新计算数据集并更新 UI 但是 当显示输出 图 时 我必须再次重新计算 因为o
  • 无法解析 com.android.support:appcompat-v7:28.0.0

    对此有很多不同的问题 但使用时存在问题v7 28 0 v7 28 v7 28 0 0 rc02但是当我同步我的项目时 我收到此错误 无法解决 app debug compileClasspath 的依赖关系 可以 无法解析 com andr
  • 如何防止 Android 设备从 Qt 应用程序进入睡眠状态

    我正在 Android 上部署 Qt 应用程序 需要防止设备进入待机状态 否则 我的线程会被中断 而且我的 BLE 连接也会丢失 我发现这样 如何以编程方式防止 Android 设备进入睡眠状态 应执行此 Java 代码 PowerMana
  • 如何知道每次通话/短信的 SimSlot 号码?

    您只知道广播接收器中的 sim 插槽号 经过一个月的研究 我得到了一个对我来说效果很好的解决方案 如下所示 首先将 android permission READ PHONE STATE 权限添加到您的清单文件中 实现电话事件接收器 为您的
  • 如何在 android 文本视图中使用 getlinecount()

    我想知道我的文本视图中有多少行 我已经设置了文本视图文本 然后我想获取文本视图中需要多少行 我使用 mytextview getLineCount 但它不起作用 它总是返回 0 有人能帮我吗 您需要发布获取行数的方法 这是示例代码 imag
  • C# Windows 服务自终止服务

    如何让服务自行终止 Environment Exit 将导致应用程序启动 但服务保持运行 任何想法 您可以使用 SCM 从服务本身关闭您的服务 System ServiceProcess ServiceController svc new
  • 启用 CORS 的服务器不拒绝请求

    我正在尝试使用快递Cors使用我的 resitfy 服务器 它似乎并没有拒绝来自其他 ip 的请求 我在本地工作 所以我尝试将 origin 设置为随机公共 IP 但我的所有请求仍在处理中 这是我的路线 module exports fun
  • Hibernate:删除多对多关联

    我有两个具有多对多关联的表 数据库片段 loads Id Name sessions Id Date 会话负载 LoadId会话ID Hibernate 映射片段 loads hbm xml
  • 跨数据库外键错误

    这是我的第一个数据库 DB1 的模型 from django db import models class Company models Model name models CharField max length 100 null Tru
  • 初始化 Objective-C 类别中的静态变量

    我试图创建一个静态变量来存储图像字典 不幸的是 我能找到的初始化它的最好方法是检查使用该变量的每个函数 由于我是在类别内创建此变量 因此我不能仅在初始化程序内初始化它 有没有更简洁的方法来初始化 navigationBarImages st
  • Typescript:对象和基元之间的 keyof typeof union 始终是 never

    首先 我的问题的一些背景信息 我有一个项目 在其中我通过 Socket IO 接收一个对象 因此我没有关于它的类型信息 此外 它是一种相当复杂的类型 因此需要进行大量检查以确保接收到的数据良好 问题是我需要访问由接收到的对象中的字符串指定的