web-dev-qa-db-fra.com

Typescript Key-Valeur Relation Conserver Object.Entries Type

La frappe pour Object.entries Fourni par Tyresscript a le type de retour [string, T][] Mais je recherche un type générique Entries<O> Pour représenter la valeur de retour de cette fonction qui maintient la relation entre les clés et les valeurs.

Par exemple. Lors d'un type d'objet comme

type Obj = {
    a: number,
    b: string,
    c: number
}

Je cherche un type Entries<O> Cela se traduit par l'un des types ci-dessous (ou quelque chose de similaire) lorsqu'il est fourni avec Obj:

(["a", number] | ["b", string] | ["c", number])[]
[["a", number], ["b", string], ["c", number]]
(["a" | "c", number] | ["b", string])[]

Que ce n'est pas correct pour tous les cas d'utilisation d'objet.entries ( voir ici ) n'est pas un problème pour mon cas particulier.


Solution éprouvée et échouée:

type Entries<O> = [keyof O, O[keyof O]][] ne fonctionne pas pour cela car il ne conserve que les clés et les valeurs possibles, mais pas la relation entre ces comme Entries<Obj> est ["a" | "b" | "c", number | string].

type Entry<O, K extends keyof O> = [K, O[K]]
type Entries<O> = Entry<O, keyof O>[]

Ici, la définition de Entry fonctionne comme prévu, par exemple. Entry<Obj, "a"> est ["a", number] Mais l'application de la deuxième ligne avec keyof O Comme la variable de deuxième type conduit à nouveau au même résultat que le premier essai.

8
Malte Laukötter

Lorsque vous souhaitez associer chaque clé avec quelque chose qui dépend de ce type de cette touche, utilisez un type mappé :

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

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

La deuxième version, qui a un type de tuple contenant les propriétés au lieu d'une union, est beaucoup plus difficile à construire; Il est possible de convertir une union en tuple mais vous ne devriez essentiellement pas le faire.

La troisième version est gérable, mais un peu plus compliqué que la première version: vous avez besoin PickByValue de cette réponse .

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

Lien de jeu

5
kaya3