Programmierung & Entwicklung
JavaScript und TypeScript lernen
JavaScript und TypeScript lernen: praxisnaher Einstieg für Web, async, DOM, Node und sauberen Umstieg auf TypeScript, Schritt für Schritt.
KI-generiert JavaScript ist überall: im Browser, auf dem Server, in Build-Tools. Ohne JavaScript kommst du in der Webentwicklung nicht weit. Und ohne TypeScript wirst du bei wachsenden Projekten schnell den Überblick verlieren. Dieser Guide zeigt dir einen pragmatischen Weg vom ersten Script bis zur sauberen TypeScript-Codebasis.
JavaScript verstehen: Was du wirklich brauchst
Bevor du TypeScript anfasst, brauchst du ein solides JavaScript-Fundament. Du musst nicht jede Sprach-Ecke auswendig kennen, aber diese Bausteine sollten sitzen:
- Datentypen:
number,string,boolean,null,undefined, Arrays, Objekte, Funktionen - Variablen:
let,constund warumvarheute kaum noch sinnvoll ist - Funktionen: Funktionsdeklarationen, Funktionsausdrücke, Arrow Functions
- Kontrollstrukturen:
if,switch,for,while,for...of - Module:
importundexportmit ES-Modulen - Fehlerbehandlung:
try,catch,finally, eigene Fehlerobjekte
Ein kleines Beispiel, das viele Grundlagen kombiniert:
// greetings.js
export function greetUser(name) {
if (!name) {
throw new Error('Name ist erforderlich');
}
const greeting = `Hallo ${name}, willkommen in der JS-Welt!`;
return greeting;
}
// main.js
import { greetUser } from './greetings.js';
try {
console.log(greetUser('Maria'));
} catch (error) {
console.error('Fehler:', error.message);
}
Wenn du solche Beispiele ohne Stolpern lesen, erklären und anpassen kannst, bist du bereit für die nächsten Schritte.
Sync vs. Async: Warum JavaScript anders tickt
JavaScript läuft in der Regel in einem Single Thread. Statt viele Threads zu starten, arbeitet es mit einem Event Loop und asynchronem Code. Das ist entscheidend für:
- HTTP-Requests im Browser
- Dateizugriffe in Node.js
- Datenbankabfragen in Backends
- Timer und Benutzerinteraktionen
Die klassischen Werkzeuge dafür sind:
- Callbacks
- Promises
asyncundawait
Callbacks sind historisch wichtig, aber für neue Projekte solltest du direkt mit Promises und async/await arbeiten.
Promises und async/await im Alltag
Ein typischer HTTP-Request im Browser:
async function loadUsers() {
const response = await fetch('https://api.example.com/users');
if (!response.ok) {
throw new Error('Request fehlgeschlagen: ' + response.status);
}
const users = await response.json();
return users;
}
loadUsers()
.then(users => {
console.log('Benutzer:', users);
})
.catch(error => {
console.error('Fehler beim Laden:', error.message);
});
Wichtige Punkte, die du verstehen solltest:
asyncmacht aus einer Funktion eine Promise-funktion, egal ob du explizit ein Promise zurückgibst.awaitpausiert die Funktion, bis das Promise erfüllt oder abgelehnt ist.- Fehler in
async-Funktionen landen im zugehörigencatchdes Promise-Chains oder imtry/catchinnerhalb der Funktion.
Ein typischer Stolperstein sind mehrere unabhängige Requests, die du unnötig nacheinander abarbeitest. Besser:
async function loadData() {
const [users, posts] = await Promise.all([
fetch('/api/users').then(r => r.json()),
fetch('/api/posts').then(r => r.json())
]);
return { users, posts };
}
Verstehe, wann paralleles Warten mit Promise.all sinnvoll ist und wann du bewusst sequenziell bleiben musst.
DOM im Browser: Interaktion mit der Seite
Im Browser ist der DOM dein Spielfeld. Du musst wissen, wie du:
- Elemente auswählst:
document.querySelector,querySelectorAll - Inhalte und Attribute änderst:
textContent,innerHTML,setAttribute - Events behandelst:
addEventListener - Formulare ausliest und validierst
Ein kleines, aber realistisches Beispiel:
const form = document.querySelector('#login-form');
const messageBox = document.querySelector('#message');
form.addEventListener('submit', event => {
event.preventDefault();
const email = form.elements.email.value;
const password = form.elements.password.value;
if (!email || !password) {
messageBox.textContent = 'Bitte E-Mail und Passwort eingeben.';
return;
}
messageBox.textContent = `Eingeloggt als ${email}`;
});
Wenn du mit solchen Snippets kleine UI-Funktionen in bestehende Webseiten einbauen kannst, bist du auf einem guten Weg.
Node.js: JavaScript außerhalb des Browsers
Mit Node.js läuft JavaScript auf dem Server oder auf deinem Rechner für Skripte und Tooling. Wichtige Unterschiede zum Browser:
- Kein DOM, dafür Zugriff auf Dateisystem, Netzwerk, Prozesse
- Andere globale Objekte:
process,__dirname,require(CommonJS) oder ES-Module mitimport - Oft andere APIs, zum Beispiel
fsfür Dateizugriffe
Ein einfaches Node-Script, das Daten aus einer JSON-Datei lädt:
import { readFile } from 'node:fs/promises';
async function loadConfig() {
const raw = await readFile('./config.json', 'utf-8');
return JSON.parse(raw);
}
loadConfig()
.then(config => {
console.log('Config geladen:', config);
})
.catch(error => {
console.error('Fehler beim Laden der Config:', error.message);
process.exit(1);
});
Für Build-Skripte, kleine Helferlein im Projekt oder serverseitige APIs ist Node.js heute Standard. Gerade in Münchner Teams triffst du Node.js oft im DevOps-Umfeld und im Frontend-Buildprozess.
Warum TypeScript? Probleme, die du sonst früher oder später hast
Reines JavaScript ist flexibel, aber diese Flexibilität rächt sich in größeren Projekten. Typische Probleme:
- Du vertippst dich im Property-Namen, der Fehler taucht erst zur Laufzeit auf.
- Du änderst die Struktur eines Objekts, vergisst aber irgendwo eine Stelle.
- Eine Funktion erwartet eine Zahl, bekommt aber einen String aus einem Formular.
- Refactorings mit Suchen/Ersetzen sind riskant und unzuverlässig.
TypeScript setzt genau hier an. Es erweitert JavaScript um:
- Typen für Variablen, Parameter und Rückgabewerte
- Interfaces und Typ-Aliase
- Enums und Literaltypen
- Statische Analyse und bessere IDE-Unterstützung
Du schreibst weiterhin JavaScript, aber eben typisiert. Der Compiler warnt dich, bevor du den Code ausführst.
Beispiel ohne TypeScript:
function calculateDiscount(price, discountPercent) {
return price - price * (discountPercent / 100);
}
const finalPrice = calculateDiscount('100', 10); // läuft, aber liefert Unsinn
Mit TypeScript:
function calculateDiscount(price: number, discountPercent: number): number {
return price - price * (discountPercent / 100);
}
const finalPrice = calculateDiscount('100', 10);
// Fehler beim Kompilieren: Argument vom Typ "string" ist nicht dem Parameter vom Typ "number" zuweisbar.
Dieser Fehler wird gar nicht erst in dein Bundle eingebaut. Deine IDE markiert ihn sofort.
Zentrale TypeScript-Konzepte für den Einstieg
Du musst nicht alle TypeScript-Features kennen, um loszulegen. Diese Bausteine reichen für einen soliden Start:
Grundtypen und Typinferenz
TypeScript kann viel selbst ableiten:
let name = 'Anna'; // Typ: string
let age = 32; // Typ: number
let isAdmin = false; // Typ: boolean
Explizite Typen brauchst du vor allem an Schnittstellen:
function greet(name: string): string {
return `Hallo ${name}`;
}
Objekttypen und Interfaces
Statt lose Objekte zu verwenden, definierst du eine Form:
interface User {
id: number;
name: string;
email?: string; // optional
}
function printUser(user: User): void {
console.log(`User #${user.id}: ${user.name}`);
}
Das hilft dir massiv bei API-Objekten, Formularen und Konfigurationen.
Union Types und Literaltypen
Gerade bei Statuswerten und Events sind Unions Gold wert:
type Status = 'idle' | 'loading' | 'success' | 'error';
let status: Status = 'idle';
status = 'loading';
// status = 'finished'; // Fehler, nicht im erlaubten Set
Generics im Alltag
Generics wirken abstrakt, sind aber im Alltag oft simpel:
function wrapInArray<T>(value: T): T[] {
return [value];
}
const numbers = wrapInArray(5); // Typ: number[]
const names = wrapInArray('Maria'); // Typ: string[]
Du nutzt Generics ständig bei Arrays, Promises und vielen Bibliotheken, ohne sie immer explizit zu schreiben:
async function fetchUser(): Promise<User> {
const response = await fetch('/api/user');
return response.json();
}
Migrationsweg: Von JavaScript zu TypeScript ohne Big Bang
Der größte Fehler beim Umstieg ist der Versuch, ein komplettes Projekt auf einmal zu migrieren. Besser ist ein schrittweiser Ansatz.
1. TypeScript-Toolchain einführen
Zuerst richtest du TypeScript ein, ohne Code zu ändern:
tsconfig.jsonanlegen, zum Beispiel mitnpx tsc --init.- Den Compiler so konfigurieren, dass er existierenden JS-Code akzeptiert:
Wichtige Optionen für den Einstieg:
"allowJs": true"checkJs": true"strict": false(kannst du später hochdrehen)"noEmit": truefür reinen Typcheck, wenn dein Build-Tool das Bundling übernimmt
- Build-Prozess anpassen, zum Beispiel via
ts-loaderin Webpack,esbuildoder die integrierte TS-Unterstützung in Tools wie Vite.
Jetzt bekommst du bereits Typfehler für deinen JavaScript-Code, wenn du JSDoc-Kommentare nutzt.
2. JSDoc-Typen in bestehendem JavaScript nutzen
Bevor du Dateien umbenennst, kannst du Typen mit JSDoc definieren:
/**
* @typedef {Object} User
* @property {number} id
* @property {string} name
* @property {string} [email]
*/
/**
* @param {User} user
*/
function printUser(user) {
console.log(user.name);
}
TypeScript versteht diese Kommentare und kann dir Hinweise geben, auch wenn die Dateien .js heißen.
3. Schrittweise auf .ts oder .tsx umstellen
Starte mit neuen Dateien direkt in TypeScript. Für existierenden Code:
- Suche dir einen klar abgegrenzten Bereich, zum Beispiel ein Util-Verzeichnis.
- Benenne eine Datei von
.jsauf.tsum. - Ergänze minimale Typen an öffentlichen Schnittstellen.
- Löse die Typfehler, die der Compiler meldet.
- Teste den Code.
Wichtige Zwischenlösung: any. Es ist besser, einzelne Stellen bewusst mit any zu markieren, als das gesamte Typensystem abzuschalten.
function parseConfig(raw: any): Config {
// TODO: Typen genauer machen
return {
host: raw.host,
port: Number(raw.port)
};
}
So weißt du später, wo du nachschärfen musst.
4. Strikter werden, wenn die Basis steht
Wenn der Großteil deines Codes typisiert ist, kannst du nach und nach:
"strict": trueaktivieren"noImplicitAny": truesetzen"strictNullChecks": trueaktivieren
Mach das nicht alles auf einmal, sondern schrittweise und mit Blick auf die Fehlermeldungen.
Praxisfokus: Wo du starten solltest
JavaScript und TypeScript sind riesige Themen. Für einen Einstieg mit Fokus auf Web- und Tooling-Aufgaben empfehle ich folgende Reihenfolge:
-
Grundlagen JavaScript im Browser Kleine DOM-Manipulationen, Event-Handling, einfache Fetch-Requests.
-
Asynchrones JavaScript verstehen Promises,
async/await, Fehlerbehandlung, paralleles vs. sequenzielles Warten. -
Node.js als Werkzeugkasten Kleine CLI-Skripte, Dateien lesen und schreiben, einfache HTTP-Requests, Automatisierung im Projekt.
-
TypeScript in neuen Modulen Neue Features direkt in
.tsschreiben, einfache Typen, Interfaces, Unions. -
Schrittweise Migration alter Bereiche JSDoc-Typen, dann Umbenennen in
.ts, dann striktere Typen.
Wenn du das strukturiert durchgehst und dir Zeit für eigene Mini-Projekte nimmst, bist du schnell an dem Punkt, an dem du produktiv und sicher mit JavaScript und TypeScript arbeiten kannst. Für tiefergehende Schulungen, gerade auch in Präsenz in München, findest du passende Angebote und aktuelle Termine bei cmt.de.
Nächster Schritt
Passenden Kurs zu Programmierung finden.
Feste Termine, erfahrene Trainer, Präsenz in München und Durchführungsgarantie. Buchen kannst du direkt auf cmt.de.