TypeScript för JavaScript-utvecklare: En praktisk guide
Typannoteringar, interfaces, generics och konfiguration. Allt du behöver för att gå från JavaScript till TypeScript utan att tappa farten.
Du kan JavaScript. Du vet hur closures fungerar, du hanterar promises i sömnen och du har debuggat undefined is not a function fler gånger än du vill erkänna. Frågan är inte om du ska lära dig TypeScript — det är hur du gör det utan att tappa farten.
TypeScript är inte ett nytt språk. Det är JavaScript med ett typsystem som hjälper dig hitta buggar innan de når produktion. Allt giltigt JavaScript är giltigt TypeScript. Du kan migrera gradvis, fil för fil.
Grundläggande typannoteringar
Det enklaste sättet att börja är att lägga till typer på funktionsparametrar och returvärden. TypeScript infererar mycket automatiskt, men explicita typer på funktionsgränser gör koden självdokumenterande.
// JavaScript
function calculateDiscount(price, percentage) {
return price * (1 - percentage / 100);
}
// TypeScript — tydligare kontrakt
function calculateDiscount(
price: number,
percentage: number
): number {
return price * (1 - percentage / 100);
}
// TypeScript fångar felet vid kompilering:
calculateDiscount("199", 10);
// Error: Argument of type 'string' is not
// assignable to parameter of type 'number'
// Grundläggande typer
let name: string = "Erik";
let age: number = 32;
let isActive: boolean = true;
let tags: string[] = ["frontend", "react"];
let coordinates: [number, number] = [59.33, 18.07];Notera att du sällan behöver annotera variabler — TypeScript infererar typen från tilldelningen. let age = 32 ger automatiskt typen number. Annotera bara när inferensen inte räcker.
Interfaces och typer
Interfaces beskriver formen på objekt. De är kontraktet som säger "ett User-objektmåste ha dessa fält med dessa typer". Det låter kanske byråkratiskt, men det sparar timmar av debugging.
interface User {
id: string;
name: string;
email: string;
role: "admin" | "user" | "moderator"; // Union type
createdAt: Date;
avatar?: string; // Valfritt fält
}
// TypeScript tvingar dig att inkludera alla fält
const user: User = {
id: "u-123",
name: "Anna Svensson",
email: "anna@example.se",
role: "admin",
createdAt: new Date(),
// avatar är valfritt — behöver inte anges
};
// Utökade interfaces
interface AdminUser extends User {
role: "admin"; // Mer specifik
permissions: string[];
lastLogin: Date;
}
// Type aliases för komplexa typer
type ApiResponse<T> = {
data: T;
meta: {
page: number;
totalPages: number;
totalItems: number;
};
};
// Användning med generics
type UserListResponse = ApiResponse<User[]>;Skillnaden mellan interface och type? Interfaces kan utökas med extends och deklareras om (declaration merging). Types är mer flexibla för unions, intersections och mappade typer. I praktiken: använd interfaces för objekt, types för allt annat.
Generics — skriver du en funktion som funkar med flera typer?
Generics låter dig skriva funktioner och typer som fungerar med olika datatyper utan att förlora typinformation. Tänk på det som en variabel för typer.
// Utan generics — du tappar typinformation
function getFirst(items: any[]): any {
return items[0];
}
const first = getFirst([1, 2, 3]); // Typ: any 😞
// Med generics — typen bevaras
function getFirst<T>(items: T[]): T | undefined {
return items[0];
}
const first = getFirst([1, 2, 3]); // Typ: number
const name = getFirst(["a", "b"]); // Typ: string
// Generics med constraints
interface HasId {
id: string;
}
function findById<T extends HasId>(
items: T[],
id: string
): T | undefined {
return items.find(item => item.id === id);
}
// Fungerar med alla typer som har ett id-fält
const user = findById(users, "u-123"); // Typ: User
const product = findById(products, "p-1"); // Typ: Product
// Generics i React-komponenter
interface ListProps<T> {
items: T[];
renderItem: (item: T) => React.ReactNode;
keyExtractor: (item: T) => string;
}
function List<T>({ items, renderItem, keyExtractor }: ListProps<T>) {
return (
<ul>
{items.map(item => (
<li key={keyExtractor(item)}>
{renderItem(item)}
</li>
))}
</ul>
);
}Strikt konfiguration med tsconfig
En ny TypeScript-installation bör alltid ha strict: true aktiverat. Det slår på alla strikta kontroller på en gång. Att aktivera det i ett befintligt projekt kan vara smärtsamt — då är det bättre att aktivera en kontroll i taget.
// tsconfig.json — rekommenderad konfiguration
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"noUncheckedIndexedAccess": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"outDir": "./dist",
"rootDir": "./src",
"declaration": true,
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}noUncheckedIndexedAccess är en av de viktigaste inställningarna som inte ingår i strict. Den tvingar dig att hantera fallet att array- och objektåtkomst kan returnera undefined. Det fångar en hel kategori runtime-fel.
Migrera gradvis — fil för fil
Du behöver inte konvertera hela projektet på en dag. Byt namn på .js-filer till .ts (eller .tsx för React) en i taget. Börja med de mest använda utility-funktionerna och arbeta dig utåt.
Använd // @ts-ignore eller any tillfälligt för att komma förbi typproblem du inte vill lösa just nu — men behandla dem som teknisk skuld, inte som en permanent lösning.
Fler guider om modern webbutveckling hittar du i vår JavaScript-guide och webbutveckling 2026.