Typescript Key-Value сохраняющий отношение Object.entries тип - PullRequest
3 голосов
/ 10 февраля 2020

Набор для Object.entries, предоставляемый типом сценария, имеет тип возврата [string, T][], но я ищу обобщенный c тип 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 ( см. Здесь ), не является проблемой для моего конкретного c случая.


Пробное и неудачное решение:

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 в качестве переменной второго типа снова приводит к тому же результату, что и первая попытка.

1 Ответ

4 голосов
/ 10 февраля 2020

Если вы хотите связать каждый ключ с чем-то, зависящим от типа этого ключа, используйте сопоставленный тип :

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])[]

Playground Link

...