Typescript键值关系保留Object.entries类型

时间:2020-02-09 22:30:10

标签: typescript typescript-generics

由typescript提供的Object.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(see here)用例来说,这都不是正确的,这对我的具体情况来说不是问题。


尝试并失败的解决方案:

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作为第二类型变量的应用会再次产生与第一次尝试相同的结果。

2 个答案:

答案 0 :(得分:8)

当您想将每个按键与取决于该按键类型的某些东西配对时,请使用mapped type

type Entries<T> = {
    [K in keyof T]: [K, T[K]];
}[keyof T][];

type Test = Entries<Obj>;
// (["a", number] | ["b", string] | ["c", number])[]

第二个版本具有包含属性而不是并集的元组类型,很难构建。 it is possible to convert a union to a tuple,但您基本上不应该这样做。

第三个版本是可管理的,但比第一个版本复杂一些:您需要this answer中的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])[]

Playground Link

答案 1 :(得分:2)

我们可以使专用功能如下:

depictObjectKeyType<O>(o: O) {
    return Object.keys(o) as (keyof O)[];
}

depictEntriesKeyType<T>(obj: T): Entries<T> {
    return Object.entries(obj) as any;
}

并用作:

this.depictEntriesKeyType(data).forEach(....