Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Typescript 将对象转换为KV值数组_Typescript_Typescript Typings_Typescript Generics - Fatal编程技术网

Typescript 将对象转换为KV值数组

Typescript 将对象转换为KV值数组,typescript,typescript-typings,typescript-generics,Typescript,Typescript Typings,Typescript Generics,我想将一个对象转换为一个键/值对数组。例如: const dict = { foo: 1, bar: 2, baz: "hi" }; const arr = dictToArray(dict); 其中,arr将被转换为一个类型强的表示,类似于: [ ["foo", { foo: 1 }], ["bar", { bar: 2 }], ["baz", { baz: "hi" }] ]

我想将一个对象转换为一个键/值对数组。例如:

const dict = { foo: 1, bar: 2, baz: "hi" };
const arr = dictToArray(dict);
其中,
arr
将被转换为一个类型强的表示,类似于:

[
  ["foo", { foo: 1 }],
  ["bar", { bar: 2 }],
  ["baz", { baz: "hi" }]
]
从运行时的角度来看,这是非常简单的,但我很难让打字过程顺利进行。我对转换的实施是:

export function dictToArray<T extends NonNullable<{}>>(obj: T): DictArray<T> {
  const out: any = [];

  for (const key of Object.keys(obj)) {
    out.push([key, { [key]: obj[key as keyof T] }]);
  }

  return out as DictArray<T>;
}
导出函数dictToArray(obj:T):DictArray{
const out:any=[];
for(对象的常量键。键(obj)){
out.push([key,{[key]:obj[key as keyof T]});
}
以数组形式返回;
}
其中,实用程序功能/类型为:

export type DictArray<T> = [keyof T, Pick<T, keyof T>][];
导出类型DictArray=[keyof T,Pick][];
我认为失败的是
DictArray
的定义,尤其是Pick引用。我这样说是因为数组中的每个元组都包含正确的运行时数据,但是元组的第二个元素,即键值对,被键入为完整对象
T

在对象赋值中,我会使用
{[K In keyof T]:V}
类型的赋值映射每个道具,但我不确定数组的可比语法是什么。我猜答案就在那里


请注意,所需的
dictToArray
函数类型可能会与中提到的问题发生冲突,即TypeScript中的对象类型是打开的,并且在运行时值可能包含比编译器已知的更多的属性。这:

function keys<T extends object>(obj: T) {
  return Object.keys(obj) as Array<keyof T>;
}
我们正在制作一个函数,它遍历T的
键中的每个键
K
,并为它生成
[K,Pick]
。如果
T
看起来像
{x:1,y:2}
,这使得类似于
{x:[“x”,{x:1}],y:[“y”,{y:2}]}
,它具有所需的属性值,但仍然嵌套在对象类型中。。。因此,我们使用
keyof T
创建这个对象,以获得所需的
[“x”,{x:1}]|[“y”,{y:2}]

您可以验证这是否为您提供了合理的类型:

const arr = dictToArray(dict);
/* const arr: DictArray<{
    foo: number;
    bar: number;
    baz: string;
}> */
除了编译器不知道对象属性的值这一事实之外(您让编译器推断类型,从而将它们扩展到
number
string
,而不是
1
2
“hi”
)。。。呃,我离题了


我知道您想要这种类型:

[
  ["foo", { foo: 1 }],
  ["bar", { bar: 2 }],
  ["baz", { baz: "hi" }]
]
[
  ["foo", { foo: number }],
  ["bar", { bar: number }],
  ["baz", { baz: string }]
]
这似乎代表了出现的条目的顺序。在JavaScript中,对象属性顺序在技术上是可以观察到的,尽管它并不总是按照人们期望的方式运行()。但在TypeScript类型中,对象属性顺序不应该是可见的。类型
{foo:number,bar:number,baz:string}
等同于类型
{bar:number,baz:string,foo:number}
。您不应该进行任何类型的系统测试来区分两者。有时可以从类型系统中挑出订单信息,但这是一个糟糕的想法,因为它将是不确定的()

因此,没有原则性的方法要求编译器为您提供上述类型,而不是

[
  ["foo", { foo: number }],
  ["baz", { baz: string }],
  ["bar", { bar: number }]
]
或任何其他订单。我们可以让
DictArray
为您提供所有可能的顺序的并集,这是在可以想象的范围内的,但这将扩展得非常糟糕,即使在小的情况下也可能不特别有用。所以,除非你想知道如何生成它,否则我就不麻烦了



对于长度不定的数组,我不确定是否可以这样做。您完全可以创建固定长度的数组,其中数组的每个元素都有一个确定的(不同的)类型,但我认为需要某种运行时类型(TypeScript显然不支持这种类型),才能从原始对象中的组合类型复制出不可预测的混合类型。@kshetline可能是。。。但当推断出一个对象的键也是未知长度时,这是可能的。。。这是六个一个,半打另一个。。。但我想这并不意味着TS支持它
不可空
只是
{}
;您可能希望将其缩减为一个简单的代码,这样其他人就不会因为看似无关的代码而分心。使用没有推理站点的
K
键的
Keys
功能(旁白:为什么不
Keys
)也是如此;为什么不直接使用
keyof T
?除非你在问这个问题,否则不清楚为什么它是问题的一部分,除了它碰巧是你的一些其他代码。在我的回答中,我可能会重写这些内容,但不会解释重写内容,因为它们与问题无关。@jcalz
Keys
告诉类型系统它是keyof T而不是Object.Keys(T)。至于NonNullable,我已经删除了它,但它只是在JS
null
中,从某种角度来看,它被认为是一个“对象”,但我想这不会传递给TS。@jcalz现在都被删除了(包括游乐场链接),这是一个很好的解决方案(但我开始意识到这正是我应该从您那里得到的)。订购不是我的事。。。我从来没想过能从对象键中获得订单。我将键作为一个单独的元素添加,以帮助筛选和引用键/值。
[
  ["foo", { foo: number }],
  ["bar", { bar: number }],
  ["baz", { baz: string }]
]
[
  ["foo", { foo: number }],
  ["baz", { baz: string }],
  ["bar", { bar: number }]
]