583 Stimmen

Typdefinition im Objektliteral in TypeScript

In TypeScript-Klassen ist es zum Beispiel möglich, Typen für Eigenschaften zu deklarieren:

class className {
  property: string;
};

Wie deklariert man den Typ einer Eigenschaft in einem Objektliteral?

Ich habe den folgenden Code ausprobiert, aber er lässt sich nicht kompilieren:

var obj = {
  property: string;
};

Ich erhalte die folgende Fehlermeldung:

Der Name 'string' existiert nicht im aktuellen Bereich

Mache ich etwas falsch oder ist das ein Fehler?

635voto

Brian Terlson Punkte 9180

Sie sind ziemlich nah dran, Sie müssen nur noch die = mit einer : . Sie können ein Objekttyp-Literal (siehe Spezifikation Abschnitt 3.5.3) oder eine Schnittstelle verwenden. Die Verwendung eines Objekttyp-Literal kommt dem nahe, was Sie haben:

var obj: { property: string; } = { property: "foo" };

Sie können aber auch eine Schnittstelle verwenden

interface MyObjLayout {
    property: string;
}

var obj: MyObjLayout = { property: "foo" };

367voto

Rick Love Punkte 11623

Update 2019-05-15 (Verbesserte Code-Muster als Alternative)

Nach vielen Jahren der Nutzung const und von funktionalerem Code zu profitieren, würde ich in den meisten Fällen davon abraten, meine ursprünglichen Antworten zu verwenden (die Überschriften unter diesem Abschnitt, d.h. bei der Erstellung von Objekten, das Typsystem in einen bestimmten Typ zu zwingen, anstatt es Typen ableiten zu lassen, ist oft ein Hinweis darauf, dass etwas falsch ist).

Stattdessen würde ich empfehlen, Folgendes zu verwenden const Variablen so weit wie möglich zu reduzieren und dann im letzten Schritt das Objekt zu komponieren:

const id = getId();
const hasStarted = true;
...
const hasFinished = false;
...
return { hasStarted, hasFinished, id };
  • Dadurch wird alles korrekt eingegeben, ohne dass eine explizite Eingabe erforderlich ist.
  • Sie müssen die Feldtypen nicht erneut eingeben.
  • Dies führt meiner Erfahrung nach zum saubersten Code.
  • Dies ermöglicht dem Compiler eine bessere Zustandsüberprüfung (wenn Sie z. B. an mehreren Stellen zurückkehren, stellt der Compiler sicher, dass immer derselbe Objekttyp zurückgegeben wird - was Sie dazu ermutigt, den gesamten Rückgabewert an jeder Position zu deklarieren - was eine völlig klare Absicht für diesen Wert darstellt).

Bonus: Optionale Felder 2022-09-29

const id = getId();
const optionalField = getOptionalValue();
return {
    id,
    // This will always exist as a key in the object but it might be undefined
    optionalField,
    // This will only exist as a key in the object if it has a truthy value
    ...optionalField2 ? { optionalField } : {},
    // This will only exist as a key in the object if it is not null or undefined
    ...optionalField2 != null ? { optionalField } : {},
};

Zusatz 2020-02-26

Wenn Sie tatsächlich eine Art, die Sie können lazily initialisiert werden müssen: Markieren Sie, dass es sich um einen nullbaren Union-Typ (null oder Type) handelt. Das Typsystem wird Sie daran hindern, ihn zu verwenden, ohne vorher sicherzustellen, dass er einen Wert hat.

Unter tsconfig.json stellen Sie sicher, dass Sie strenge Nullprüfungen aktivieren:

"strictNullChecks": true

Dann verwenden Sie dieses Muster und erlauben Sie dem Typsystem, Sie vor versehentlichem null/undefiniertem Zugriff zu schützen:

const state = {
    instance: null as null | ApiService,
    // OR
    // instance: undefined as undefined | ApiService,

};

const useApi = () => {
    // If I try to use it here, the type system requires a safe way to access it

    // Simple lazy-initialization 
    const api = state?.instance ?? (state.instance = new ApiService());
    api.fun();

    // Also here are some ways to only access it if it has value:

    // The 'right' way: Typescript 3.7 required
    state.instance?.fun();

    // Or the old way: If you are stuck before Typescript 3.7
    state.instance && state.instance.fun();

    // Or the long winded way because the above just feels weird
    if (state.instance) { state.instance.fun(); }

    // Or the I came from C and can't check for nulls like they are booleans way
    if (state.instance != null) { state.instance.fun(); }

    // Or the I came from C and can't check for nulls like they are booleans 
    // AND I was told to always use triple === in javascript even with null checks way
    if (state.instance !== null && state.instance !== undefined) { state.instance.fun(); }
};

class ApiService {
    fun() {
        // Do something useful here
    }
}

In 99 % der Fälle sollten Sie die folgenden Schritte nicht durchführen:

Update 2016-02-10 - Zum Umgang mit TSX (Danke @Josh)

Verwenden Sie die as Betreiber für TSX.

var obj = {
    property: null as string
};

Ein längeres Beispiel:

var call = {
    hasStarted: null as boolean,
    hasFinished: null as boolean,
    id: null as number,
};

Original-Antwort

Verwenden Sie den Cast-Operator, um dies kurz und bündig zu machen (durch Casting von null auf den gewünschten Typ).

var obj = {
    property: <string> null
};

Ein längeres Beispiel:

var call = {
    hasStarted: <boolean> null,
    hasFinished: <boolean> null,
    id: <number> null,
};

Das ist viel besser als zwei Teile zu haben (einen für die Deklaration von Typen, den zweiten für die Deklaration von Standardwerten):

var callVerbose: {
    hasStarted: boolean;
    hasFinished: boolean;
    id: number;
} = {
    hasStarted: null,
    hasFinished: null,
    id: null,
};

99voto

LogicalBranch Punkte 4104

Ich bin überrascht, dass das noch niemand erwähnt hat, aber man könnte einfach eine Schnittstelle namens ObjectLiteral das akzeptiert key: value Paare des Typs string: any :

interface ObjectLiteral {
  [key: string]: any;
}

Dann würden Sie es so verwenden:

let data: ObjectLiteral = {
  hello: "world",
  goodbye: 1,
  // ...
};

Ein zusätzlicher Bonus ist, dass Sie diese Schnittstelle beliebig oft wiederverwenden können, und zwar für so viele Objekte, wie Sie möchten.

Viel Glück!

61voto

streletss Punkte 5736

Sie können vordefinierte Hilfstypen verwenden Record<Keys, Type> :

const obj: Record<string, string> = {
  property: "value",
};

Sie ermöglicht die Angabe von Schlüsseln für Ihr Objektliteral:

type Keys = "prop1" | "prop2"

const obj: Record<Keys, string> = {
  prop1: "Hello",
  prop2: "Aloha",
  something: "anything" // TS Error: Type '{ prop1: string; prop2: string; something: string; }' is not assignable to type 'Record<Keys, string>'.
                        //   Object literal may only specify known properties, and 'something' does not exist in type 'Record<Keys, string>'.
};

Und einen Typ für den Eigenschaftswert:

type Keys = "prop1" | "prop2"
type Value = "Hello" | "Aloha"

const obj1: Record<Keys, Value> = {
  prop1: "Hello",
  prop2: "Hey", // TS Error: Type '"Hey"' is not assignable to type 'Value'.
};

26voto

Ryan Cavanaugh Punkte 204278

Wenn Sie versuchen, eine Typ-Anmerkung zu schreiben, lautet die Syntax:

var x: { property: string; } = { property: 'hello' };

Wenn Sie versuchen, ein Objektliteral zu schreiben, lautet die Syntax:

var x = { property: 'hello' };

In Ihrem Code wird versucht, einen Typnamen an einer Wertposition zu verwenden.

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