Beim Arbeiten mit dem FormData-Interface in JavaScript, wo Daten als Schlüssel/Wert-Paare hinzugefügt werden, gibt es keine eingebaute Möglichkeit, die Typensicherheit der hinzugefügten Schlüssel durchzusetzen. Das kann zu Tippfehlern, fehlenden Schlüsseln und unerwarteten Laufzeitfehlern führen. Aber in TypeScript können wir dieses Problem lösen, indem wir eine strenge Schlüsselvalidierung durchsetzen.

Ich benötigte diese Lösung selbst, als ich meine Formularwerte an eine API sendete. Später stellte ich fest, dass ich mehrere typografische Fehler in mehr als einem Schlüssel/Wert-Paar gemacht hatte, das ich zu meiner Nutzlast hinzufügen wollte. Da FormData jeden String als Schlüssel akzeptiert, konnte ich die falschen Strings übergeben und mit der API-Anfrage fortfahren.

Nachdem dies passiert war, suchte ich nach einer Möglichkeit, sicherzustellen, dass TypeScript diese Fehler nicht zulässt.

Dieser Artikel zeigt Ihnen, wie Sie FormData-Schlüssel typensicher mit TypeScript machen können.

Voraussetzungen

Um den größtmöglichen Nutzen aus diesem Artikel zu ziehen, sollten Sie ein grundlegendes Verständnis der folgenden Themen haben:

  1. JavaScript-Programmierung

  2. Grundlagen von TypeScript, insbesondere wie Interfaces, Typen und der keyof-Operator funktionieren

  3. das FormData-Interface

Wenn Sie neu in TypeScript oder FormData sind, empfehle ich, sich die offizielle Dokumentation von TypeScript und den Leitfaden von MDN zu FormData anzusehen, bevor Sie fortfahren.

Schritt 1: Definieren Sie Ihre erlaubten Schlüssel

Der alte Weg

Der Standardweg, Daten mit FormData anzuhängen, besteht darin, dies manuell mit einfachen Zeichenfolgen zu tun:

const payload = new FormData();

payload.append("id", "1122");
payload.append("name", "Clark Kent");

payload.append("agge", "36"); // Tippfehler im Schlüssel ist erlaubt

Im obigen Code-Schnipsel sehen Sie, dass ein Tippfehler beim Definieren eines Schlüssels für age auftrat. TypeScript markiert dies jedoch nicht als Fehler, was zu Fehlern führen könnte, wenn diese Daten mit einer API-Anfrage gesendet werden.

Der bessere Weg

Statt die Schlüssel manuell einzugeben, definieren Sie sie in einem Objektschema mit einer TypeScript-Schnittstelle.

interface MyAllowedData {
    id: number;
    name: string;
    age: number;
}

Alternativ können Sie sie mit Typen definieren:

type MyAllowedData = {
    id: number;
    name: string;
    age: number;
}

Sie können entweder Typen oder Schnittstellen verwenden, es ist nur eine Frage der Präferenz. Weitere Informationen dazu, wie sie sich unterscheiden, finden Sie in diesem offiziellen TypeScript-Dokumentations-Beispielbereich.

Definieren Sie als nächstes einen Unionstyp aus jedem Schlüssel in Ihrer Schnittstelle.

type MyFormDataKeys = keyof MyAllowedData
// das ist dasselbe wie `type MyFormDataKeys = 'id' | 'name' | 'age'`

Der keyof-Operator hilft dabei, einen Unionstyp der Schlüssel eines Objekttyps zu erstellen, daher ist er sehr nützlich, wenn Sie keinen Unionstyp manuell für ein größeres Objekt mit vielen Schlüsseln definieren möchten.

Schritt 2: Erstellen Sie eine Hilfsfunktion zum Anhängen

Jetzt, da Sie Ihre streng typisierten Schlüssel definiert haben, ist der nächste Schritt, eine Hilfsfunktion zu erstellen, die sicherstellt, dass nur gültige Schlüssel an FormData angehängt werden.

function appendToFormData (formData: FormData, key: MyFormDataKeys, value: string) {
  formData.append(key, value);
};

Die Funktion appendToFormData nimmt drei Argumente entgegen. So funktioniert es:

  • Das erste Argument, formData, ist eine Instanz des FormData-Objekts. Hier werden Schlüssel/Wert-Paare angehängt, bevor sie in einer API-Anfrage gesendet werden.

  • Das zweite Argument, key, ist der Schlüsselname des Feldes, das Sie anhängen möchten. Sein Typ ist MyFormDataKeys, der Unionstyp, den wir erstellt haben, um sicherzustellen, dass nur die von uns definierten Schlüssel an FormData angehängt werden.

  • Das dritte Argument ist ein String value, der den Wert darstellt, der mit dem Schlüssel angehängt werden soll.

Beachten Sie, dass FormData akzeptiert nur die string und Blob Typen als Werte in jedem Schlüssel/Wert-Paar. In diesem Leitfaden arbeiten wir nur mit Zeichenfolgenwerten – aber denken Sie daran, dass Sie Blob-Werte verwenden können, um Dateien an API-Anfragen anzuhängen.

Jetzt wollen wir die Funktion testen:

const payload = new FormData();

appendToFormData(payload, "id", "19282"); // ✅ Erlaubt
appendToFormData(payload, "name", "Lenny Brown"); // ✅ Erlaubt
appendToFormData(payload, "age", "20"); // ✅ Erlaubt

appendToFormData(payload, "someOtherKey", "89"); // ❌ TypeScript Fehler: Argument des Typs 'someOtherKey' ist nicht zuweisbar.

Schritt 3: Verwenden Sie die Hilfsfunktion nach dem Absenden des Formulars

Jetzt fügen wir unsere Felder zu FormData hinzu, bevor wir sie an eine API senden.

const handleSubmitForm = () => {
  const payload = new FormData();
   appendToFormData(payload, "id", "19282");
   appendToFormData(payload, "name", "Lenny Brown");
   appendToFormData(payload, "age", "20");

  // Payload über API senden
  fetch("/api/submit", { method: "POST", body: payload });
};

Felder aus einem Objekt anhängen

Alternativ, wenn Sie bereits Ihren gesamten Payload in einem Objekt haben, können Sie das Anhängen jedes Feldes einzeln vermeiden, indem Sie die Funktion wie folgt implementieren:

const handleSubmitForm = () => {
  // alle Ihre Felder in einem Objekt
  const formValues: MyAllowedData = {
    id: 1123,
    name: 'John Doe',
    age: 56
  }
  const payload = new FormData();

  Object.entries(formValues).forEach(([key, value]) => {
    appendToFormData(payload, key as MyFormDataKeys, `${value}`); // Verwenden Sie Template-Literale, um den Wert einzufügen
  });

  // Payload über API senden
  fetch("/api/submit", { method: "POST", body: payload });
};

Im obigen Snippet verwenden wir Object.entries, um über jedes Schlüssel/Wert-Paar in einem Objekt zu iterieren, damit es dem FormData-Objekt hinzugefügt werden kann. Beachten Sie, dass der Wert in jedem Paar, egal ob es sich um einen String oder eine Zahl handelt, als String über Template-Strings übergeben wird, um einen Typkonflikt in TypeScript mit dem value-Argument in unserer Hilfsfunktion zu vermeiden.

Fazit

Durch die Nutzung des keyof-Operators von TypeScript können wir FormData.append() vollständig typsicher machen. Diese einfache Technik hilft, Schlüsselkonflikte zu vermeiden und macht Ihre API-Anfragen zuverlässiger.

Lassen Sie mich wissen, was Sie über den Artikel denken, und zögern Sie nicht, Vorschläge zu machen, von denen Sie glauben, dass sie meine Lösung verbessern könnten.

Danke fürs Lesen!