FJS26 · V50 · TISDAG

Generics,
utility types
och moduler

Typer som fungerar för många typer, och typer som skapas ur andra typer.

Chas Academy · Tisdag 8 december 2026


Idag

01Varför generics?02Generiska funktioner och typer03extends: begränsa T04Utility types05Moduler i TypeScript06Efter passet
GENERICS, UTILITY TYPES OCH MODULER2 / 26
01

Varför
generics?

VARFÖR GENERICS?


Samma funktion, olika typer

Vi vill ha första elementet i en lista. Vilken lista som helst.

En per typ

const firstNumber = (items: number[]) =>
  items[0];
const firstString = (items: string[]) =>
  items[0];
// och så vidare...

any

const first = (items: any[]) => items[0];

const x = first([10, 20]);
// x: any
x.toUpperCase(); // inget fel, kraschar
GENERICS, UTILITY TYPES OCH MODULER4 / 26

VARFÖR GENERICS?


any tappar typen, T tar den med sig

anytypen försvinner på vägennumber[]first(items)anyut kommer vad som helst, och TypeScriptslutar kontrollera<T>typen följer med från in till utnumber[]first<T>numberstring[]first<T>stringT fylls i när funktionen används
GENERICS, UTILITY TYPES OCH MODULER5 / 26
02

Generiska
funktioner
och typer

GENERICS


En typparameter

Funktionen

const first = <T>(items: readonly T[])
  : T | undefined => items[0];

Användningen

first([10, 20, 30]);
// T = number, ger number | undefined

first(['Ada', 'Grace']);
// T = string

first<string>([]);
// T skriven för hand
GENERICS, UTILITY TYPES OCH MODULER7 / 26

GENERICS


Generics ni redan har använt

Vinkelparenteserna har funnits där hela tiden.

Array<T>

const prices: Array<number>
  = [39, 49];
// samma som number[]

Map<K, V>

const stock =
  new Map<string, number>();
stock.set('kaffe', 12);

Promise<T>

const load = async ()
  : Promise<string> => {
  return 'klart';
};
GENERICS, UTILITY TYPES OCH MODULER8 / 26

GENERICS


Generiska typer

En typ kan också ha typparametrar.

Typen

type Pair<A, B> = {
  first: A;
  second: B;
};

Användningen

const price: Pair<string, number> = {
  first: 'kaffe',
  second: 39,
};
GENERICS, UTILITY TYPES OCH MODULER9 / 26
03

extends:
begränsa T

EXTENDS


T får vara vad som helst, och det är problemet

Utan begränsning

const longest = <T>(a: T, b: T) =>
  a.length >= b.length ? a : b;
// Fel: Property 'length' does
// not exist on type 'T'

Med extends

const longest = <T extends { length: number }>(
  a: T,
  b: T,
): T => (a.length >= b.length ? a : b);

longest('kaffe', 'te');   // 'kaffe'
longest([1, 2], [1, 2, 3]);
longest(10, 20);          // Fel
GENERICS, UTILITY TYPES OCH MODULER11 / 26

EXTENDS


En egen generisk funktion

Funktionen

type HasId = { id: string };

const findById = <T extends HasId>(
  items: readonly T[],
  id: string,
): T | undefined =>
  items.find((item) => item.id === id);

Fungerar för allt med ett id

findById(products, 'bulle')?.price;
findById(users, 'u1')?.email;
// TypeScript vet att det är en
// produkt respektive en användare
GENERICS, UTILITY TYPES OCH MODULER12 / 26

EXTENDS


Varför inte bara HasId?

Utan typparameter

const findById = (
  items: readonly HasId[],
  id: string,
): HasId | undefined => ...;

findById(products, 'bulle')?.price;
// Fel: Property 'price' does not
// exist on type 'HasId'

Skillnaden

Utan T kommer bara HasId ut, och resten av produkten är borta för TypeScript. Med T följer hela typen med, och extends garanterar bara att id finns.

GENERICS, UTILITY TYPES OCH MODULER13 / 26
”

Använd en generic när typen ut beror på typen in. Annars räcker en vanlig typ.

04

Utility
types

Typer som skapas ur andra typer.

UTILITY TYPES


Utgångspunkten

En produkt

type Product = {
  id: string;
  name: string;
  price: number;
  category: 'dryck' | 'bröd' | 'mat';
  description: string;
};

Behoven

En uppdatering har bara några fält. Ett kort visar bara namn och pris. En ny produkt har inget id än. Ska vi skriva fyra typer för hand?

GENERICS, UTILITY TYPES OCH MODULER16 / 26

UTILITY TYPES


Partial, Pick och Omit

Partial<T>

Alla fält valfria.

const update = (
  p: Product,
  changes: Partial<Product>,
): Product =>
  ({ ...p, ...changes });

Pick<T, K>

Bara några fält.

type ProductCard = Pick<
  Product,
  'name' | 'price'
>;

Omit<T, K>

Allt utom några fält.

type NewProduct =
  Omit<Product, 'id'>;
GENERICS, UTILITY TYPES OCH MODULER17 / 26

UTILITY TYPES


Record och Readonly

Record<K, V>

type Category = Product['category'];

const labels: Record<Category, string> = {
  dryck: 'Drycker',
  bröd: 'Bröd och bullar',
  mat: 'Mat',
};
// saknas en kategori blir det fel

Readonly<T>

const frozen: Readonly<Product> = latte;
frozen.price = 10;
// Fel: Cannot assign to 'price'
// because it is a read-only property
GENERICS, UTILITY TYPES OCH MODULER18 / 26

UTILITY TYPES


Kombinera dem

Typen

type ProductUpdate =
  Partial<Omit<Product, 'id'>>;

Läs inifrån och ut

Ta Product, ta bort id, och gör resten valfritt. Ändras Product följer ProductUpdate med.

GENERICS, UTILITY TYPES OCH MODULER19 / 26

Övning

Typa kaféets formulär

I src/2-utility-types.ts: skriv updateProduct, ProductCard, NewProduct med createProduct, categoryLabels och ProductUpdate. Ta sedan bort en nyckel ur categoryLabels och läs felet.

Tid

15 min

Mål

Du kan skapa nya typer ur en befintlig typ i stället för att skriva dem för hand.

GENERICS, UTILITY TYPES OCH MODULER20 / 26
05

Moduler i
TypeScript

MODULER


Var bor typerna?

types.ts

export type Category = 'dryck' | 'bröd' | 'mat';

export type Product = {
  id: string;
  name: string;
  price: number;
  category: Category;
};

Andra filer

import type { Product } from './types';
import { products } from './products';

const cheap: Product[] = products
  .filter((p) => p.price < 40);
GENERICS, UTILITY TYPES OCH MODULER22 / 26

MODULER


import type

Vad det gör

Importerar bara typen. Raden finns inte kvar i den byggda JavaScript-koden, eftersom typer inte finns när koden körs.

verbatimModuleSyntax

Med den i tsconfig.json är det ett fel att importera en typ utan type. Då ser man direkt vad som är typ och vad som är kod.

import { Product } from './types';
// Fel: 'Product' is a type and must
// be imported using a type-only import
GENERICS, UTILITY TYPES OCH MODULER23 / 26
”

Typerna finns bara medan du skriver koden. När den körs finns bara JavaScript kvar.

06

Efter passet

EFTER PASSET


Efter passet

  • Din egen kod: finns det en funktion där typen ut beror på typen in? Då är den en kandidat för en egen generic.
  • Code-along: gör klart del 1–3, och kör npm run check.
  • I morgon: data utifrån. DOM:en, unknown, type guards och Zod.
  • Läs: Generics och Utility Types i TypeScript-handboken.
GENERICS, UTILITY TYPES OCH MODULER26 / 26