Website-Suche

javascript - Ein Indexsignatur-Parametertyp kann kein Vereinigungstyp sein. Erwägen Sie stattdessen die Verwendung eines abgebildeten Objekttyps


Ich versuche, das folgende Muster zu verwenden:

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

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

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

Das erscheint mir sehr einfach, jedoch erhalte ich folgenden Fehler:

Ein Index-Signatur-Parameter-Typ kann kein Vereinigungstyp sein. Ziehen Sie stattdessen in Betracht, einen gemappten Objekttyp zu verwenden.

Was mache ich falsch?

Antwort #1

Sie können den TS-"in"-Operator verwenden und Folgendes tun:

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

Mehr über den in-Operator

Antwort #2

Die einfachste Lösung ist die Verwendung von Record

type OptionRequirements = Record<Options, OptionRequirement>

Sie können es auch selbst wie folgt implementieren:

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

Dieses Konstrukt ist nur für type verfügbar, jedoch nicht für interface.

Das Problem in Ihrer Definition besteht darin, dass Sie sagen, der Schlüssel Ihrer Schnittstelle sollte vom Typ Options sein, wobei Options ein Enum ist, nicht ein String, eine Zahl oder ein Symbol.

Der key in Options bedeutet „für diejenigen spezifischen Schlüssel, die im Union-Typ Options enthalten sind“.

Der type-Alias ist flexibler und leistungsfähiger als interface.

Wenn Ihr Typ nicht in einer Klasse verwendet werden muss, wählen Sie type statt interface.

Antwort #3

In meinem Fall:

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

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

Ich habe es behoben, indem ich den in-Operator anstelle von : verwendet habe

~~~

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

Antwort #4

Ich hatte ein ähnliches Problem, aber in meinem Fall ging es um eine andere Feld-Eigenschaft in der Schnittstelle, daher ist meine Lösung als Beispiel mit einer optional Feld-Eigenschaft mit einem Enum für Schlüssel:

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
}

Antwort #5

In meinem Fall mussten die Eigenschaften optional sein, also habe ich diesen generischen Typ erstellt.

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

Dann benutze es so:

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

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

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

Beispiel

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

Antwort #6

Anstatt ein Interface zu verwenden, verwenden Sie einen gemappten Objekttyp

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

type OptionKeys = keyof typeof Option;

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

type OptionRequirements = {                 // note type, not interface
  [key in OptionKeys]: OptionRequirement;   // key in
}

Verwandte Artikel