Existe-t-il un moyen de déclarer un type en tapuscrit qui «extrait» le type interne d'un tableau?

Exemple:

Disons que j'ai déjà quelque chose comme ça dans ma base de code:

export interface Cache {
    events: Event[],
    users: User[]
}
type CacheType = Event[] | User[];

//or maybe: 
//   type TypeOfProperty = T[keyof T];
//   type CacheType = TypeOfProperty<Cache>; 

Ce que je veux, c'est quelque chose qui équivaudrait à ceci:

type InnerCacheType = Event | User;

Mais sans le retaper manuellement chaque fois que j'ajoute quelque chose à Cache ou CacheType

Est-ce possible dans Typescript?

15
Lennart Hoffmann 21 avril 2017 à 11:21

3 réponses

Meilleure réponse

Ceci est possible avec Typescript 2.8+. Vous pouvez déclarer un type Unpacked<T> comme suit:

type Unpacked<T> = T extends (infer U)[] ? U : T;

Maintenant vous pouvez faire

type InnerCacheType = Unpacked<CacheType>; // Event | User

Ceci est une définition condensée du type Unpacked donnée dans le documentation.

13
Ingo Bürk 14 sept. 2018 à 12:00

Supposons que vous puissiez utiliser TypeScript 2.1 ou supérieur, sinon il n'y a aucun moyen d'atteindre ce que vous recherchez.

Gardez également à l'esprit que vous prenez pour acquis que toutes les propriétés de l'interface Cache seront des tableaux. Si ce n'est pas le cas, votre question devient insensée, je ferai donc également cette hypothèse.

De manière générale, CacheType peut être écrit comme

type CacheType = Cache[typeof Cache];

Y compris toutes les propriétés héritées. Le type obtenu est équivalent à Event[] | User[], mais l'extraction des composants du tableau à partir d'un tel type d'union est irréalisable.

La solution utilise des types mappés. Le InnerCacheType que vous recherchez peut être écrit comme

type InnerCacheType = MappedCacheType[typeof MappedCacheType];

type MappedCacheType = { [P in keyof Cache]: Cache[P][0]; };

En fait, le dernier type équivaut à

{ events: Event; users: User; }

Veuillez noter que TypeScript conserve les noms identiques à ceux d'origine.

Pour résumer, sans tenir compte de votre cas d'utilisation, la manière d'exprimer le type de composant d'un type de tableau T est T[0].

3
FstTesla 21 avril 2017 à 11:01

Cela pourrait également être réalisé avec une requête de type. c'est à dire.

type CacheType = Event[] | User[];

type InnerCacheType = CacheType[number]; // Event | User

TS Playground

5
lonewarrior556 12 mai 2020 à 18:56