576 votes

Un type de paramètre de signature d'index ne peut pas être un type d'union. Envisagez d'utiliser un type d'objet mappé à la place

J'essaie d'utiliser le modèle suivant :

enum Option {
  ONE = 'one',
  TWO = 'two',
  THREE = 'three'
}

interface OptionRequirement {
  someBool: boolean;
  someString: string;
}

interface OptionRequirements {
  [key: Option]: OptionRequirement;
}

Cela me semble très simple, mais j'obtiens l'erreur suivante :

Un type de paramètre de signature d'index ne peut pas être un type d'union. Pensez à utiliser un type d'objet mappé à la place.

Qu'est-ce que je fais de mal ?

5 votes

Type de key ne peut être qu'une chaîne, un nombre ou un symbole. Enum ne l'est pas.

839voto

Vous pouvez utiliser l'opérateur TS "in" et faire cela :

enum Options {
  ONE = 'one',
  TWO = 'two',
  THREE = 'three',
}
interface OptionRequirement {
  someBool: boolean;
  someString: string;
}
type OptionRequirements = {
  [key in Options]: OptionRequirement; // Note that "key in".
}

27 votes

Erm, ça ne compile pas ? Le site TypeScript playground dit : "Un nom de propriété calculé dans une interface doit faire référence à une expression dont le type est un type littéral ou un type 'symbole unique'."

41 votes

Changement interface OptionRequirements à type OptionRequirements

9 votes

Ça ne marche pas pour moi : Un nom de propriété calculé dans une interface doit faire référence à une expression dont le type est un type littéral ou un type 'symbole unique'.

244voto

unional Points 4754

La solution la plus simple consiste à utiliser Record

type OptionRequirements = Record<Options, OptionRequirement>

Vous pouvez également le mettre en œuvre vous-même comme :

type OptionRequirements = {
  [key in Options]: OptionRequirement;
}

Cette construction est uniquement disponible pour type mais pas interface .

Le problème dans votre définition est de dire que la clé de votre interface doit être de type Options , donde Options est une énumération, et non une chaîne de caractères, un nombre ou un symbole.

El key in Options signifie "pour ces clés spécifiques qui sont dans le type d'union Options".

type est plus souple et plus puissant que l'alias interface .

Si votre type ne doit pas être utilisé en classe, choisissez type sur interface .

0 votes

C'était cool. Maintenant, que faire si j'ai besoin que cette variable soit indéfinie, comment l'initialiser plus tard ?

0 votes

@KatLimRuiz : [key in Options]: OptionRequirement | undefined

0 votes

Intéressant... si tu fais quelque chose comme keyof Options au sein de la Record cela fonctionne bien, mais si vous le faites par la voie "implémentez-le vous-même" vous obtenez une erreur de syntaxe, incapable de faire [keyof Options]: OptionRequirement . Dans mon cas, mon Option est un type, pas un enum.

124voto

AmerllicA Points 1

Dans mon cas :

export type PossibleKeysType =
  | 'userAgreement'
  | 'privacy'
  | 'people';

interface ProviderProps {
  children: React.ReactNode;
  items: {
    //    this colon was issue
    [key: PossibleKeysType]: Array<SectionItemsType>;
  };
}

Je l'ai corrigé en utilisant in au lieu d'utiliser l'opérateur :

~~~

interface ProviderProps {
  children: React.ReactNode;
  items: {
    //      use "in" operator
    [key in PossibleKeysType]: Array<SectionItemsType>;
  };
}

48voto

Kurkov Igor Points 46

J'ai eu un problème similaire, mais dans mon cas, il s'agissait d'une propriété d'un autre champ dans l'interface. Ma solution, à titre d'exemple, est la suivante en option avec un enum pour les clés :

export enum ACTION_INSTANCE_KEY {
  cat = 'cat',
  dog = 'dog',
  cow = 'cow',
  book = 'book'
}

type ActionInstances = {
  [key in ACTION_INSTANCE_KEY]?: number; // cat id/dog id/cow id/ etc // <== optional
};

export interface EventAnalyticsAction extends ActionInstances { // <== need to be extended
  marker: EVENT_ANALYTIC_ACTION_TYPE; // <== if you wanna add another field to interface
}

28voto

Alazzawi Points 91

Dans mon cas, j'avais besoin que les propriétés soient facultatives, j'ai donc créé ce type générique.

type PartialRecord<K extends string | number | symbol, T> = { [P in K]?: T; };

Alors utilisez-le comme tel :

type MyTypes = 'TYPE_A' | 'TYPE_B' | 'TYPE_C';

interface IContent {
    name: string;
    age: number;
}

interface IExample {
    type: string;
    partials: PartialRecord<MyTypes, IContent>;
}

Exemple

const example : IExample = {
    type: 'some-type',
    partials: {
        TYPE_A : {
            name: 'name',
            age: 30
        },
        TYPE_C : {
            name: 'another name',
            age: 50
        }
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X