TypeScript Academy · leksjon

Tilordning fra skjema til type

Forstå hvordan tabelldefinisjoner blir til TypeScript-typer.

Leksjon 1 av 413 trinn

Tilordning fra skjema til type er en gratis leksjon i TypeScript Academy på CoddyKit. Dette er leksjon 1 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i TypeScript Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i TypeScript Academy inneholder totalt 4 leksjoner.

Fra tabelldefinisjon til radtype

En typesikker ORM lar Dem beskrive en databasetabell én gang og automatisk utlede TypeScript-radtypen fra den. De trenger aldri å skrive radformen manuelt; den beregnes fra kolonnedefinisjonene.

I denne leksjonen bruker vi en Drizzle-lignende pgTable som gjennomgående eksempel.

Definering av en tabell

En tabell er et objekt som kobler kolonnenavn til kolonnebyggere. Hver bygger inneholder en SQL-type samt modifikatorer 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 kolonnetyper

Hver kolonnebygger har en phantom-type som beskriver verdien den produserer. serial og integer tilsvarer number, text tilsvarer string, og boolean tilsvarer boolean.

Byggeren holder også oversikt over om kolonnen kan være 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 styrer nullbarhet

Den viktigste faktoren for radtypen er notNull(). En kolonne uten dette blir T | null i den utledede typen, fordi SQL tillater 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- og insert-modeller

Radtypen for lesing (select) er forskjellig fra typen for skriving (insert). Ved insert blir kolonner med standardverdier eller automatisk inkrementering valgfrie.

import { InferInsertModel } from "drizzle-orm";

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

Slik fungerer inferensen

Under panseret er hver kolonnebygger en generisk klasse, for eksempel PgColumn<{ data: number; notNull: true }>. En mappet type går gjennom hver nøkkel i tabellen og leser disse flaggene.

// 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-er og egendefinerte typer

Kolonner med streng-unioner mappes til litterale unioner, ikke bare string. Det betyr at en ugyldig statusverdi gir en kompileringsfeil.

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"
});

Standardverdier

.default() gjør en kolonne valgfri ved insert, men lar den fortsatt være til stede ved select. Typesystemet koder «has default», slik at det bare kan endre valgfriheten der det er riktig.

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)

Hvorfor dette er viktig

Fordi radtypen er avledet, oppdateres typen for hvert spørringsresultat automatisk når skjemaet endres. Gi en kolonne nytt navn, så markerer kompilatoren alle foreldede referanser. Det finnes ingen separat sannhetskilde som kan komme ut av synk.

Et lite eksempel fra ende til ende

For å sette det sammen: definer én gang, utled typen, og bruk den som kontrakt for en repository-funksjon.

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];
}

Fallgruve: Du glemmer notNull

Hvis du glemmer notNull() på en kolonne som faktisk er obligatorisk, blir den utledede typen T | null og tvinger frem unødvendige nullsjekker i hele koden. Sørg for at skjemaet gjenspeiler virkeligheten.

Hurtigsjekk

Test forståelsen din av koblingen mellom skjema og type.

Oppsummering

Du har lært at en tabelldefinisjon er den eneste sannhetskilden: Kolonnebyggere inneholder fantomtyper, mappede typer går gjennom tabellen for å bygge radtypen, notNull() styrer nullbarheten, og select- og insert-modellene har ulik valgfrihet. Endre skjemaet, så følger alle resultattypene automatisk etter.

Gratis å komme i gang

Lær deg TypeScript med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
101
Leksjoner
352

Ofte stilte spørsmål

Er leksjonen «Tilordning fra skjema til type» gratis?

Ja – hele teksten i «Tilordning fra skjema til type» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av TypeScript Academy-kurset, kan du oppgradere til CoddyKit PRO. Kurset i TypeScript Academy inneholder totalt 4 leksjoner.

Hva lærer jeg i «Tilordning fra skjema til type»?

Forstå hvordan tabelldefinisjoner blir til TypeScript-typer. Du øver på TypeScript Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med TypeScript Academy?

Ingen tidligere erfaring er nødvendig. TypeScript Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 1 av 4.

Hvor lang tid tar leksjonen «Tilordning fra skjema til type»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne TypeScript Academy-leksjonen?

Ja. Alle TypeScript Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. Tilordning fra skjema til type
  2. Typesikker konstruksjon av spørringer
  3. Inferere formen på spørringsresultater
  4. Relasjoner og joins med typer
← Tilbake til TypeScript Academy