Supposons que j'aie un interface décrivant une bibliothèque dont les éléments ressemblent à ceci :

interface MyItem {
  category: string,
  title: string
}

Maintenant, j'ai un fichier de configuration plein de ces MyItems :

const myLibrary: MyItem[] = [
  {
    category: "dogs",
    title: "Fuzzy quadrupeds" 
  },
  { 
    category: "snakes",
    title: "Slithery reptiles"
  },
  ...
]

Maintenant, j'aimerais créer un type composé de tous les category dans MyItem[]

Si je fais ça : type Category = typeof MyItem[number]["category"] j'obtiens string.

Si je supprime la saisie de myLibrary (c'est-à-dire const myLibrary = [ {...} ]) et que j'obtiens ce que je veux :

Cela signifie que type Category = typeof MyItem[number]["category"] me donne le type d'union que je veux de dogs | snakes mais bien sûr, je perds la saisie lors de la création de nouveaux éléments dans mon fichier de configuration.

0
Caleb Larsen 14 mars 2021 à 01:52

3 réponses

Meilleure réponse

Ne complique pas


type Categorías = 'Food' | 'categoy1' | 'cstegory2'

interface MyItem {
  category: Categories;
  title: string
}

const myLibrary: MyItem[] = [
  {
    category: "dogs",
    title: "Fuzzy quadrupeds" 
  },
  { 
    category: "snakes",
    title: "Slithery reptiles"
  },
  ...
0
Ernesto 15 mars 2021 à 01:49

Nous voulons restreindre les éléments dans myLibrary de telle sorte qu'ils doivent implémenter MyItem, mais nous voulons le faire d'une manière qui préserve des types spécifiques d'éléments spécifiques et n'élargit pas le type à simplement MyItem.

Il est difficile de le faire simplement en attribuant un type à la constante. Un modèle couramment utilisé consiste à créer la constante via une fonction d'identité. Avec une fonction, nous pouvons utiliser la syntaxe extends pour garantir que T extends MyItem[] tout en gardant T spécifique.

J'ai dû utiliser as const pour obtenir les noms de catégorie littéraux, je devais donc également autoriser readonly dans les arguments de la fonction.

interface MyItem {
  category: string,
  title: string
}

const buildLibrary = <T extends readonly MyItem[]>(library: T): T => library;

const myLibrary = buildLibrary([
  {
    category: "dogs",
    title: "Fuzzy quadrupeds" 
  },
  { 
    category: "snakes",
    title: "Slithery reptiles"
  }
] as const);

type Categories = (typeof myLibrary)[number]['category'] // "dogs" | "snakes"

Lien du terrain de jeu Typescript

1
Linda Paiste 15 mars 2021 à 00:52

Si je vous comprends bien, vous voulez ceci : Comment créer un type enum comme dans TypeScript ? puis spécifiez MyItem comme

interface MyItem: {
    category: MyDogSnakeType,
    title: string
}
0
Lars Wissler 13 mars 2021 à 22:59