Mappning från schema till typ
Så blir tabelldefinitioner TypeScript-typer.
Mappning från schema till typ är en gratis lektion i TypeScript Academy på CoddyKit. Detta är lektion 1 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för TypeScript Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i TypeScript Academy innehåller totalt 4 lektioner.
Från tabelldefinition till radtyp
En typsäker ORM låter dig beskriva en databastabell en gång och automatiskt härleda dess TypeScript-radtyp. Du behöver aldrig skriva radens struktur för hand; den beräknas från kolumndefinitionerna.
I den här lektionen använder vi en Drizzle-liknande pgTable som löpande exempel.
Definiera en tabell
En tabell är ett objekt som mappar kolumnnamn till kolumnbyggare. Varje byggare kodar en SQL-typ samt modifierare som notNull eller 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(),
});Inferens av kolumntyper
Varje kolumnbyggare innehåller en fantomtyp som beskriver värdet den producerar. serial och integer mappas till number, text till string och boolean till boolean.
Byggaren håller också reda på om kolumnen kan vara null.
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 styr nullbarhet
Den enskilt viktigaste faktorn för radtypen är notNull(). En kolumn UTAN detta blir T | null i den härledda typen, eftersom SQL tillåter NULL som standard.
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- och insertmodeller
Radtypen för läsning (select) skiljer sig från typen för skrivning (insert). Vid insert blir kolumner med standardvärden eller automatisk inkrementering valfria.
import { InferInsertModel } from "drizzle-orm";
type NewUser = InferInsertModel<typeof users>;
// {
// id?: number; // serial has a default -> optional
// name: string;
// age?: number | null;
// isAdmin: boolean;
// }Så fungerar typinferensen
Under huven är varje kolumnbyggare en generisk klass, till exempel PgColumn<{ data: number; notNull: true }>. En mappad typ går igenom varje nyckel i tabellen och läser av dessa flaggor.
// 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;
};Enum- och anpassade typer
Kolumner med strängunioner mappas till literala unioner, inte bara till string. Det innebär att ett ogiltigt statusvärde blir ett kompileringsfel.
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"
});Standardvärden
.default() gör en kolumn valfri vid insert, men behåller den som obligatorisk vid select. Typsystemet kodar att kolumnen "har ett standardvärde", så att valfriheten bara ändras där det är lämpligt.
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)Varför detta är viktigt
Eftersom radtypen är härledd uppdateras typen för varje frågeresultat automatiskt när schemat ändras. Byt namn på en kolumn så markerar kompilatorn alla gamla referenser. Det finns ingen andra källa till sanning som kan hamna ur synk.
Ett litet exempel från början till slut
Om vi sätter ihop allt: definiera en gång, härled typen och använd den som kontrakt för en 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];
}Fallgrop: att glömma notNull
Om du glömmer notNull() för en kolumn som faktiskt är obligatorisk blir den härledda typen T | null, vilket tvingar fram onödiga nullkontroller i hela koden. Se till att schemat återspeglar verkligheten.
Snabb kontroll
Testa din förståelse av mappningen från schema till typ.
Sammanfattning
Du har lärt dig att en tabelldefinition är den enda källan till sanning: kolumnbyggare innehåller fantomtyper, mappade typer går igenom tabellen för att bygga radtypen, notNull() styr nullbarheten och select- och insertmodeller skiljer sig åt när det gäller valfrihet. Ändra schemat så följer alla resultattyper automatiskt med.
Lär dig TypeScript med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 101
- Lektioner
- 352
Vanliga frågor
Är lektionen ”Mappning från schema till typ” gratis?
Ja – hela texten till ”Mappning från schema till typ” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i TypeScript Academy, kan Ni uppgradera till CoddyKit PRO. Kursen i TypeScript Academy innehåller totalt 4 lektioner.
Vad lär jag mig i ”Mappning från schema till typ”?
Så blir tabelldefinitioner TypeScript-typer. Ni övar på TypeScript Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig TypeScript Academy?
Du behöver inga förkunskaper. Utbildningen i TypeScript Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 1 av 4.
Hur lång tid tar lektionen ”Mappning från schema till typ”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här TypeScript Academy-lektionen?
Ja. Varje TypeScript Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- Mappning från schema till typ
- Typsäker konstruktion av queries
- Inferens av query-resultatens struktur
- Relationer och joins med typer