832 Stimmen

Wie weise ich einem Objekt in TypeScript dynamisch Eigenschaften zu?

Wenn ich einem Objekt in Javascript programmatisch eine Eigenschaft zuweisen wollte, würde ich es so machen:

var obj = {};
obj.prop = "value";

In TypeScript erzeugt dies jedoch einen Fehler:

Die Eigenschaft 'prop' existiert nicht bei einem Wert vom Typ '{}'.

Wie soll ich einem Objekt in TypeScript eine neue Eigenschaft zuweisen?

1095voto

Akash Punkte 12079

Index-Typen

Es ist möglich, zu bezeichnen obj als any aber das widerspricht dem Sinn und Zweck der Verwendung von Type Script. obj = {} impliziert obj ist ein Object . Markierung als any macht keinen Sinn. Um die gewünschte Konsistenz zu erreichen, könnte eine Schnittstelle wie folgt definiert werden.

interface LooseObject {
    [key: string]: any
}

var obj: LooseObject = {};

ODER um es kompakt zu machen:

var obj: {[k: string]: any} = {};

LooseObject kann Felder mit einer beliebigen Zeichenkette als Schlüssel akzeptieren und any Typ als Wert.

obj.prop = "value";
obj.prop2 = 88;

Die eigentliche Eleganz dieser Lösung besteht darin, dass Sie typsichere Felder in die Schnittstelle aufnehmen können.

interface MyType {
    typesafeProp1?: number,
    requiredProp1: string,
    [key: string]: any
}

var obj: MyType ;
obj = { requiredProp1: "foo"}; // valid
obj = {} // error. 'requiredProp1' is missing
obj.typesafeProp1 = "bar" // error. typesafeProp1 should be a number

obj.prop = "value";
obj.prop2 = 88;

Record<Keys,Type> Versorgungsart

Aktualisierung (August 2020): @transang hat dies in den Kommentaren angesprochen

Record<Keys,Type> ist ein Utility-Typ in typescript. Er ist eine wesentlich sauberere Alternative für Schlüssel-Wert-Paare, bei denen die Eigenschaftsnamen nicht bekannt sind. Es ist erwähnenswert, dass Record<Keys,Type> ist ein benannter Alias für {[k: Keys]: Type} donde Keys y Type sind Generika. Dies macht es IMO wert, hier erwähnt zu werden

Zum Vergleich,

var obj: {[k: string]: any} = {};

wird

var obj: Record<string,any> = {}

MyType kann nun durch eine Erweiterung des Record-Typs definiert werden

interface MyType extends Record<string,any> {
    typesafeProp1?: number,
    requiredProp1: string,
}

Damit ist zwar die ursprüngliche Frage beantwortet, aber die Antwort aquí von @GreeneCreations könnte eine andere Perspektive aufzeigen, wie man das Problem angehen kann.

109voto

Crwth Punkte 1844

Oder alles auf einmal:

  var obj:any = {}
  obj.prop = 5;

101voto

jmvtrinidad Punkte 3041

Diese Lösung ist nützlich, wenn Ihr Objekt einen bestimmten Typ hat. Zum Beispiel bei der Beschaffung des Objekts in einer anderen Quelle.

let user: User = new User();
(user as any).otherProperty = 'hello';
//user did not lose its type here.

86voto

basarat Punkte 230827

Ich neige dazu, die any auf der anderen Seite, d.h. var foo:IFoo = <any>{}; So etwas ist also immer noch typsicher:

interface IFoo{
    bar:string;
    baz:string;
    boo:string;     
}

// How I tend to intialize 
var foo:IFoo = <any>{};

foo.bar = "asdf";
foo.baz = "boo";
foo.boo = "boo";

// the following is an error, 
// so you haven't lost type safety
foo.bar = 123; 

Alternativ können Sie diese Eigenschaften auch als optional markieren:

interface IFoo{
    bar?:string;
    baz?:string;
    boo?:string;    
}

// Now your simple initialization works
var foo:IFoo = {};

Versuchen Sie es online

50voto

Angelo R. Punkte 2199

Auch wenn der Compiler sich beschwert, sollte er sie dennoch wie gewünscht ausgeben. Dies wird jedoch funktionieren.

const s = {};
s['prop'] = true;

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X