typescript - 打字稿键值关系保留 Object.entries 类型
问题描述
typescriptObject.entries
提供的类型具有返回类型[string, T][]
,但我正在寻找一个泛型类型Entries<O>
来表示此函数的返回值,该函数保持键和值之间的关系。
例如。当有一个对象类型时
type Obj = {
a: number,
b: string,
c: number
}
我正在寻找一种Entries<O>
在提供以下类型时会产生以下类型(或类似类型)的类型Obj
:
(["a", number] | ["b", string] | ["c", number])[]
[["a", number], ["b", string], ["c", number]]
(["a" | "c", number] | ["b", string])[]
这对于 Object.entries 的所有用例都不正确(请参阅此处),这对于我的具体情况来说没有问题。
尝试和失败的解决方案:
type Entries<O> = [keyof O, O[keyof O]][]
对此不起作用,因为它只保留可能的键和值,但不保留它们之间的Entries<Obj>
关系["a" | "b" | "c", number | string]
。
type Entry<O, K extends keyof O> = [K, O[K]]
type Entries<O> = Entry<O, keyof O>[]
这里Entry
是预期的作品的定义,例如。Entry<Obj, "a">
是["a", number]
,但是在第二行中将它keyof O
作为第二个类型变量应用会再次导致与第一次尝试相同的结果。
解决方案
这是一个解决方案,但在将其用作;的返回类型时要小心。Object.entries
这样做并不总是安全的(见下文)。
当您想将每个键与依赖于该键类型的内容配对时,请使用映射类型:
type Entries<T> = {
[K in keyof T]: [K, T[K]];
}[keyof T][];
type Test = Entries<Obj>;
// (["a", number] | ["b", string] | ["c", number])[]
第二个版本,它有一个包含属性的元组类型而不是一个联合,更难构造。可以将联合转换为元组,但您基本上不应该这样做。
第三个版本是可管理的,但比第一个版本复杂一点:你需要PickByValue
从这个答案。
type Entries3<T> = {
[K in keyof T]: [keyof PickByValue<T, T[K]>, T[K]]
}[keyof T][];
type Test3 = Entries3<Obj>;
// (["a" | "c", number] | ["b", string])[]
我想我还应该解释为什么 Typescript没有给Object.entries
. 当你有一个类似的类型type Obj = {a: number, b: string, c: number}
时,它只保证一个值具有这些属性;不保证该值也没有其他属性。例如,该值{a: 1, b: 'foo', c: 2, d: false}
可分配给类型Obj
(除了对象文字的额外属性检查)。
在这种情况下Object.entries
,将返回一个包含元素的数组['d', false]
。类型Entries<Obj>
说这不可能发生,但实际上它可以发生;所以一般来说Entries<T>
不是一个合理的返回类型Object.entries
。Object.entries
只有当您自己知道这些值没有多余的属性时,您才应该使用上述解决方案;Typescript 不会为你检查这个。
推荐阅读
- r - 如何使用 R 中的 getData 包简化和加速循环
- r - 如何解决 case when 和 mutate 的问题?
- php - 我无法连接电脑中的任何服务器
- python - 如何使用 python 的正则表达式从文本文件中删除多个标签
- python - 解决了| Python:If/elif/else 语句未按预期工作?
- php - 禁用特定送货方式的支付网关
- git - 在 Dockerfile 中:如果主分支更改,则仅克隆 git repo
- java - 二元运算符“”的错误操作数类型第一类型字符串第二类型字符串
- node.js - 删除节点模块使计算机崩溃
- ethereum - 如何创建以太坊销毁地址?