Eingabe (.proto-Schema)

Ausgabe (TypeScript)

Was dieses Tool macht

Du hast ein Protocol-Buffers-Schema und ein TypeScript-Frontend, das mit einem gRPC- oder HTTP-transcodierten Backend reden muss, das diese Messages liefert. Die offizielle Codegen-Toolchain (protoc mit ts-proto oder protobuf-ts) verlangt, dass du Tools installierst, Plugins konfigurierst und einen Build-Schritt einbindest. Dieser Konverter erledigt dieselbe Arbeit in deinem Browser — einfügen, Output kopieren, in dein Projekt werfen.

Das Type-Mapping orientiert sich daran, wie handgeschriebene Typen in echten Codebases aussehen: string/bytesstring/Uint8Array, boolboolean, die kleineren numerischen Typen (int32, uint32, float, double) → number, und die 64-Bit-Integer-Typen (int64, uint64, fixed64, sfixed64, sint64) → string, passend zur proto3-JSON-Mapping-Spec. repeated T wird zu T[], map<K, V> wird zu Record<K, V>, verschachtelte Messages werden zu verschachtelten interface-Deklarationen.

Feldnamen werden von snake_case (Protobuf-Konvention) in camelCase (JavaScript/TypeScript-Konvention) umgewandelt — passend zum Standardverhalten des proto3-JSON-Encoders. Enums werden zu String-Literal-Union-Typen (type OrderStatus = 'ORDER_STATUS_UNSPECIFIED' | 'ORDER_STATUS_PENDING' | ...), was die meisten TypeScript-Codebases tatsächlich wollen — ohne den Laufzeit-Overhead eines enums. Der Konverter läuft komplett im Browser; nichts von deinem Schema verlässt die Seite.

So benutzt du es

Drei Schritte. Der Output ist in Sekunden bereit, in eine <code>.ts</code>-Datei eingefügt zu werden.

1

Füge dein .proto-Schema ein

Wirf das Schema in den linken Editor. syntax = "proto3"; oben ist OK aber optional. Der Parser kommt mit verschachtelten message-Blöcken, enum-Deklarationen, oneof, map<K, V> und Feldoptionen zurecht. Imports werden erkannt, aber übersprungen — füge importierte Typen inline ein, wenn du sie brauchst.

Die Feldnamen-Konvertierung läuft automatisch: order_id in .proto wird in TypeScript zu orderId. Message- und Enum-Namen bleiben wie sie sind (schon PascalCase).

2

Lies den Output

Rechts: TypeScript mit export interface für jede Message und export type mit einer String-Literal-Union für jedes Enum. Verschachtelte Typen kommen vor ihrem Parent, sodass die Datei in Deklarationsreihenfolge ist. Füge die Datei deinem Projekt hinzu und importiere die Interfaces aus deinem gRPC-Client oder Fetch-Handler.

3

Nutze die Typen

Verdrahte die Interfaces mit deinem Fetch- / gRPC-Web- / Connect-RPC-Client. Die Form passt zur proto3-JSON-Kodierung, sodass JSON-Antworten ohne manuelle Konvertierung direkt in die typisierte Form geparst werden. Passe die int64-Behandlung an, wenn dein Server eine nicht-standardmäßige JSON-Kodierung verwendet.

Wann das wirklich Zeit spart

Typen für ein neues gRPC-Frontend skizzieren

Du baust eine neue TS-App auf einem bestehenden gRPC-Service auf. Du brauchst noch keine vollständige Codegen — nur die Interface-Formen, um deine Fetch-Calls zu typisieren. Füge das .proto ein, wirf den Output in types.ts, fertig.

Eine Protobuf-API-Änderung reviewen

Ein Backend-Kollege hat einer Message Felder hinzugefügt. Du willst sehen, wie sich das auf die Frontend-Typen auswirkt, ohne den Build laufen zu lassen. Füge das neue .proto ein, diff den TypeScript-Output gegen deine aktuellen Typen, hinterlasse einen fokussierten Review-Kommentar.

Generierte Typen gegenchecken

Dein Build verwendet protobuf-ts oder ts-proto, die Typen mit eigenen Konventionen erzeugen. Füge das Schema hier ein, um eine saubere Referenz dafür zu haben, wie schlichte TS-Interfaces aussehen — nützlich für Doku oder Migrationsplanung.

Wegwerf-Skripte und einmalige Integrationen

Du schreibst ein schnelles Node-Skript, das JSON an eine gRPC-Gateway POSTet. Die ganze Protobuf-Toolchain für 30 Zeilen aufzusetzen ist übertrieben. Hol dir die Interfaces hier und du hast Typsicherheit ohne Zeremoniell.

Häufige Fragen

Wird mein Schema irgendwohin gesendet?

Nein. Der Parser und der TS-Emitter laufen komplett im Browser als JavaScript. Öffne die DevTools und schau dir den Network-Tab an, während du einfügst — null Requests. Praktisch, wenn dein Schema interne Typnamen, Package-Pfade oder irgendwas enthält, das du nicht an einen Drittanbieter schicken willst.

Warum sind int64-Felder als string typisiert?

JavaScript-Numbers sind IEEE-754-Doubles, die ab 2^53 Präzision verlieren. Das offizielle proto3-JSON-Mapping verlangt, dass int64, uint64, fixed64, sfixed64 und sint64 als JSON-Strings kodiert werden. Deshalb verwendet das TS-Interface dort string — passend zu dem, was dein Server tatsächlich sendet. Wenn du stattdessen bigint brauchst, mach Suchen-und-Ersetzen im Output.

Warum sind Enums String-Unions statt TS-Enums?

Die meisten TypeScript-Projekte bevorzugen heute String-Literal-Unions gegenüber TS-Enums — keine Laufzeitkosten, besseres Tree-Shaking, und sie passen zur proto3-JSON-Kodierung (die Enums als ihren String-Namen serialisiert). Wenn du ein const enum oder ein numerisches Enum willst, ist die Umwandlung von der Union mechanisch.

Wie wird map<K, V> behandelt?

Wird als Record<K, V> ausgegeben. Protobuf-Maps mit Nicht-String-Schlüsseln (z. B. map<int32, string>) werden zu Record<number, string>. JSON kennt nur String-Schlüssel, also sind die Schlüssel zur Laufzeit Strings, auch wenn das Proto int sagt — das ist eine Eigenheit der proto3-JSON-Spec, nicht des Konverters.

Werden Felder als optional markiert?

Nein. proto3-Felder sind in der JSON-Ausgabe immer vorhanden (mit Defaults — leerer String, 0, false, [], {}), also markiert das TypeScript-Interface jedes Feld als erforderlich. Wenn du wirklich optionale Felder willst (weil deine Runtime sie weglassen kann), füge nach jedem Feldnamen manuell ein ? ein.

Wird oneof unterstützt?

Jedes oneof-Feld wird als reguläres Interface-Feld emittiert. Der Output erzwingt nicht die "genau eins"-Bedingung, die oneof impliziert — dafür bräuchtest du eine diskriminierende Union, was von der Semantik deiner Runtime abhängt. Editier den Output von Hand, wenn du strengere Typen brauchst.

Verwandte Tools

Wenn du mit Protobuf, JSON und TypeScript arbeitest, ergänzen sich diese gut: