Tilbake til bloggen
Guide14. mars 2026

TypeScript: Hvordan typesikkerhet endret måten jeg bygger systemer på

TypeScript er ikke bare «JavaScript med typer». Det er et helt annet forhold til koden din — en kontrakt mellom deg og fremtiden din, mellom deg og teamet ditt, mellom det du tror koden gjør og det den faktisk gjør.

Jeg har brukt TypeScript som mitt primærspråk i flere år nå, og det har fundamentalt endret måten jeg tenker om systemdesign. Denne guiden handler om hvorfor, og hvilke mønstre som faktisk gjør en forskjell i produksjon.

Hvorfor TypeScript og ikke bare JavaScript?

La meg starte med en ærlig innrømmelse: jeg elsket JavaScript. Friheten. Fleksibiliteten. Muligheten til å bare bygge uten å tenke på typer.

Men den friheten har en pris. Bugs som TypeScript fanger ved kompilering, fanger JavaScript klokken 03:00 i produksjon. Den «fleksible» funksjonen som aksepterer hva som helst? Den krasjer fordi noen sendte inn undefined der du forventet et objekt.

Da jeg begynte å bygge Nextbook — en læringsplattform med kurs, quizer, brukerdata og betalingsflyt — innså jeg at JavaScript-frihet ikke skalerer. Ikke fordi språket er dårlig, men fordi kompleksiteten i et reelt system krever garantier som runtime ikke kan gi deg.

Den virkelige verdien av TypeScript er ikke typene i seg selv. Det er tre ting:

Dokumentasjon som kode. Typedefinisjoner forteller deg hva en funksjon forventer og returnerer — uten å lese implementasjonen.

Refactoring med selvtillit. Når du endrer en type, viser kompilatoren deg alt som brekker. Ikke noen ting. Alt.

Designpress. Typer tvinger deg til å tenke gjennom edge cases før du skriver logikk.

Når du IKKE bør bruke TypeScript

TypeScript er ikke alltid svaret. Noen ganger er det overkill:

  • Raske engangsskript. Trenger du å flytte noen filer eller transformere data én gang? Bruk JavaScript eller Bash.
  • Prototyping der hastighet teller. Hvis du utforsker en idé og ikke vet om den overlever uken, kan typedefinisjoner bremse flyten.
  • Shell-scripting. TypeScript i terminalen er mulig, men sjelden verdt oppsettet.

Poenget er pragmatisme. Bruk TypeScript der det gir verdi — i systemer som varer, i team som samarbeider, i kode som endres.

Mønstre jeg bruker i produksjon

Etter å ha brukt TypeScript i Nextbook og andre prosjekter har jeg landet på noen mønstre som gjør en reell forskjell. Ikke fancy type-gymnastikk, men praktiske teknikker som fanger bugs og gjør koden tydeligere.

Discriminated unions for tilstandshåndtering

Dette er kanskje det viktigste mønsteret jeg bruker. I stedet for å ha et objekt med masse optional-felt som kanskje finnes og kanskje ikke, bruker du en union der hvert variant har en felles diskriminator:

type ApiResult<T> =
  | { status: 'success'; data: T }
  | { status: 'error'; code: string; message: string }
  | { status: 'loading' };

function handleResult<T>(result: ApiResult<T>) {
  switch (result.status) {
    case 'success':
      return result.data; // TypeScript vet at data finnes her
    case 'error':
      console.error(`[${result.code}] ${result.message}`);
      return null;
    case 'loading':
      return undefined;
  }
}

Kraften her er at TypeScript vet hvilke felter som finnes i hver gren. Prøver du å aksessere result.data i error-caset, får du en kompileringsfeil. Ikke en runtime-feil. Ikke en bug i produksjon. En rød strek i editoren mens du skriver.

I Nextbook bruker vi dette mønsteret overalt — for API-responser, for UI-tilstand, for brukerautentisering. Det eliminerer en hel klasse av bugs.

Branded types for domenesikkerhet

Her er et subtilt problem: du har userId og courseId, begge er strenger. Hva hindrer deg fra å blande dem?

type UserId = string & { readonly __brand: 'UserId' };
type CourseId = string & { readonly __brand: 'CourseId' };

function createUserId(id: string): UserId { return id as UserId; }
function createCourseId(id: string): CourseId { return id as CourseId; }

function enrollUser(userId: UserId, courseId: CourseId): void {
  // TypeScript forhindrer: enrollUser(courseId, userId) — rekkefølgen betyr noe
}

I ren JavaScript er det ingenting som stopper deg fra å sende courseId der userId forventes. Med branded types gjør TypeScript det til en kompileringsfeil. I et system som Nextbook, der feil ID kan bety at en bruker får tilgang til feil kurs, er dette ikke akademisk — det er sikkerhet.

Zod-validering med typeinferens

Runtime-validering og compile-time typer lever ofte i parallelle verdener. Zod slår dem sammen:

import { z } from 'zod';

const CourseSchema = z.object({
  id: z.string().uuid(),
  title: z.string().min(1).max(200),
  chapters: z.array(z.object({
    title: z.string(),
    videoUrl: z.string().url().optional(),
    quizzes: z.array(z.string()).default([]),
  })),
  publishedAt: z.coerce.date().nullable(),
});

type Course = z.infer<typeof CourseSchema>;

function parseCourse(data: unknown): Course {
  return CourseSchema.parse(data);
}

Du definerer skjemaet én gang, og Zod gir deg både runtime-validering og TypeScript-typen. Ingen duplikasjon. Ingen drift mellom det du validerer og det du typechecke. I Nextbook bruker vi dette for all data som krysser tillitsgrenser — API-input, database-resultater, brukerinnhold.

Strict null checks som designpress

strictNullChecks i tsconfig.json er kanskje den viktigste enkeltinnstillingen. Den tvinger deg til å håndtere null og undefined eksplisitt — ingen flere «denne er sikkert aldri null»-antakelser.

Det føles irriterende de første dagene. Så innser du at hver gang kompilatoren klager, har den rett. Den verdien kan være null. Og du bør håndtere det.

Når du IKKE bør bruke TypeScript

Jeg har allerede nevnt noen tilfeller, men det er verdt å utdype:

  • Engangsskript og CLI-verktøy der Bash er enklere. Ikke alt trenger et build-steg.
  • Hvis teamet ikke kan TypeScript. Dårlige typer er verre enn ingen typer. any overalt gir en falsk følelse av sikkerhet. Invester i opplæring først.
  • Veldig små prosjekter der oppsettkostnaden ikke er verdt det. En enkel HTML-side med litt interaktivitet trenger ikke TypeScript.

Det handler ikke om at TypeScript er «bedre» enn JavaScript. Det handler om å velge riktig verktøy for riktig jobb.

Avsluttende tanker

TypeScript endret ikke bare hvilke bugs jeg fanger. Det endret måten jeg tenker om kode. Typer er ikke begrensninger — de er designbeslutninger som lever i koden. De kommuniserer intensjon. De beskytter mot misforståelser. De gjør refactoring fra en risikosport til en rutinejobb.

Hvis du skriver JavaScript i produksjon og ikke har prøvd TypeScript ordentlig: gi det to uker med strict: true. Ikke halvveis. To uker med full strikthet. Du kommer ikke til å gå tilbake.

#typescript#frontend#backend#nextbook

Nyhetsbrev

Få nye innlegg rett i innboksen.