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