0Pricing
TypeScript Academy · Lektion

Schema-zu-Typ-Zuordnung

Erfahren Sie, wie Tabellendefinitionen zu TypeScript-Typen werden.

Schema-zu-Typ-Zuordnung ist eine kostenlose TypeScript Academy-Lektion auf CoddyKit. Dies ist Lektion 1 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des TypeScript Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der TypeScript Academy-Kurs umfasst insgesamt 4 Lektionen.

Von der Tabellendefinition zum Zeilentyp

Mit einem typsicheren ORM können Sie eine Datenbanktabelle einmal beschreiben und daraus automatisch ihren TypeScript-Zeilentyp ableiten. Sie müssen die Struktur der Zeile nie von Hand schreiben; sie wird aus den Spaltendefinitionen berechnet.

In dieser Lektion verwenden wir als durchgehendes Beispiel ein Drizzle-ähnliches pgTable.

Eine Tabelle definieren

Eine Tabelle ist ein Objekt, das Spaltennamen auf Spalten-Builder abbildet. Jeder Builder beschreibt einen SQL-Typ sowie Modifikatoren wie notNull oder primaryKey.

import { pgTable, serial, text, integer, boolean } from "drizzle-orm/pg-core";

export const users = pgTable("users", {
  id: serial("id").primaryKey(),
  name: text("name").notNull(),
  age: integer("age"),
  isAdmin: boolean("is_admin").notNull(),
});

Inferenz von Spaltentypen

Jeder Spalten-Builder enthält einen Phantomtyp, der den von ihm erzeugten Wert beschreibt. serial und integer werden auf number abgebildet, text auf string und boolean auf boolean.

Der Builder verfolgt außerdem, ob die Spalte nullfähig ist.

import { InferSelectModel } from "drizzle-orm";

// Row type inferred from the table above
type User = InferSelectModel<typeof users>;
// {
//   id: number;
//   name: string;
//   age: number | null;   // not notNull -> nullable
//   isAdmin: boolean;
// }

notNull steuert die Nullbarkeit

Der wichtigste Faktor für den Zeilentyp ist notNull(). Eine Spalte ohne diese Angabe wird im abgeleiteten Typ zu T | null, da SQL standardmäßig NULL zulässt.

const posts = pgTable("posts", {
  id: serial("id").primaryKey(),
  title: text("title").notNull(),  // string
  subtitle: text("subtitle"),      // string | null
});

type Post = InferSelectModel<typeof posts>;
// { id: number; title: string; subtitle: string | null }

Select- und Insert-Modelle

Der Zeilentyp zum Lesen (select) unterscheidet sich vom Typ zum Schreiben (insert). Beim Einfügen werden Spalten mit Standardwerten oder automatischer Inkrementierung optional.

import { InferInsertModel } from "drizzle-orm";

type NewUser = InferInsertModel<typeof users>;
// {
//   id?: number;        // serial has a default -> optional
//   name: string;
//   age?: number | null;
//   isAdmin: boolean;
// }

So funktioniert die Typableitung

Intern ist jeder Spalten-Builder eine generische Klasse wie PgColumn<{ data: number; notNull: true }>. Ein gemappter Typ durchläuft jeden Schlüssel der Tabelle und liest diese Kennzeichnungen aus.

// Simplified mental model of the inference
type InferRow<T> = {
  [K in keyof T]: T[K] extends { _: { data: infer D; notNull: infer N } }
    ? N extends true ? D : D | null
    : never;
};

Enums und benutzerdefinierte Typen

Spalten mit String-Union-Typen werden auf Literal-Unions abgebildet, nicht nur auf string. Dadurch führt ein ungültiger Statuswert zu einem Kompilierungsfehler.

import { pgEnum } from "drizzle-orm/pg-core";

export const roleEnum = pgEnum("role", ["user", "admin", "owner"]);

export const members = pgTable("members", {
  id: serial("id").primaryKey(),
  role: roleEnum("role").notNull(), // "user" | "admin" | "owner"
});

Standardwerte

.default() macht eine Spalte beim Einfügen optional, lässt sie beim Lesen aber weiterhin erforderlich. Das Typsystem codiert, dass ein Standardwert vorhanden ist, und kann die Optionalität so nur an den passenden Stellen ändern.

const events = pgTable("events", {
  id: serial("id").primaryKey(),
  createdAt: text("created_at").notNull().default("now()"),
});
// Select: createdAt is string
// Insert: createdAt is optional (default fills it)

Warum das wichtig ist

Da der Zeilentyp abgeleitet wird, aktualisiert eine Schemaänderung automatisch den Typ jedes Abfrageergebnisses. Benennen Sie eine Spalte um, markiert der Compiler jede veraltete Referenz. Es gibt keine zweite Quelle der Wahrheit, die abweichen könnte.

Ein kleines Beispiel von Anfang bis Ende

Zusammengefasst: Definieren Sie etwas einmal, leiten Sie den Typ ab und verwenden Sie ihn als Vertrag für eine Repository-Funktion.

type User = InferSelectModel<typeof users>;

async function findUser(id: number): Promise<User | undefined> {
  // db.query returns rows already typed as User
  const rows = await db.select().from(users).where(eq(users.id, id));
  return rows[0];
}

Stolperfalle: notNull vergessen

Wenn Sie notNull() für eine tatsächlich erforderliche Spalte vergessen, wird der abgeleitete Typ zu T | null und erzwingt in Ihrem gesamten Code unnötige Nullprüfungen. Halten Sie das Schema wahrheitsgetreu.

Kurzer Check

Testen Sie Ihr Verständnis der Abbildung von Schema zu Typ.

Zusammenfassung

Sie haben gelernt, dass eine Tabellendefinition die einzige Quelle der Wahrheit ist: Spalten-Builder enthalten Phantom-Typen, gemappte Typen durchlaufen die Tabelle und erstellen den Zeilentyp, notNull() steuert die Nullbarkeit, und Select- und Insert-Modelle unterscheiden sich in ihrer Optionalität. Ändern Sie das Schema, folgen alle Ergebnistypen automatisch.

Häufig gestellte Fragen

Ist die Lektion „Schema-zu-Typ-Zuordnung“ kostenlos?

Ja — der vollständige Text von „Schema-zu-Typ-Zuordnung“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des TypeScript Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der TypeScript Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Schema-zu-Typ-Zuordnung“?

Erfahren Sie, wie Tabellendefinitionen zu TypeScript-Typen werden. Du übst TypeScript Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um TypeScript Academy zu starten?

Keine Vorkenntnisse erforderlich. TypeScript Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 1 von 4.

Wie lange dauert die Lektion „Schema-zu-Typ-Zuordnung“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser TypeScript Academy-Lektion Code schreiben und ausführen?

Ja. Jede TypeScript Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Schema-zu-Typ-Zuordnung
  2. Typsichere Query-Erstellung
  3. Strukturen von Query-Ergebnissen ableiten
  4. Relationen und Joins mit Typen
← Zurück zu TypeScript Academy