TypeScript

ein Superset von JavaScript

Informatik – 3. Semester

Software- und Web-Engineering I · TH Lübeck
Was ist TypeScript?
  • Release 2012, entwickelt von Microsoft
  • TypeScript ist ein SuperSet von JavaScript
    • Jedes JavaScript Programm ist ein valides TypeScript Programm
  • TS ist ein Drop-In Replacement. Ein JavaScript Codebasis kann somit iterativ durch TypeScript ersetzt werden
  • Strongly typed language
Software- und Web-Engineering I · TH Lübeck
1 Motivation & Kontext
2 JavaScript-Recap
3 Syntax & Einstieg
4 Grundlagen des Typsystems
5 Funktionen & Klassen

Wie passt das zu ihrem Projekt?

Software- und Web-Engineering I · TH Lübeck
Warum reden wir über TypeScript?
  • Gemeinsames Ziel: stabile Web-App im Team entwickeln
  • TS ergänzt vorhandenes Wissen in HTML/CSS/JS um Typsicherheit
  • Bessere Wartbarkeit, frühere Fehlermeldungen im Editor
  • Erwartung: Schnellere Reviews, weniger Runtime-Bugs
TypeScript-Logo
Logo: https://upload.wikimedia.org/
Software- und Web-Engineering I · TH Lübeck
Semesterprojekt-Fit
  • Typen für eure Domäne und die JSON-Daten der API einmal festlegen
  • Erleichtert Pair Programming & Code Reviews im Team
  • Auch im Back-End verbreitet (z. B. Node.js), bei uns läuft das Back-End mit Spring Boot
Software- und Web-Engineering I · TH Lübeck
Typfehler im Verborgenen
// calc-total.js
function calcTotal(price, tax) {
  return price + tax; // führt zu String-Konkatenation bei price="19"
}
// calc-total.ts
function calcTotal(price: number, tax: number) {
  return price + tax;
}
  • Editor warnt sofort, wenn price als String übergeben wird
Software- und Web-Engineering I · TH Lübeck
Fehlende Typen
  • Notiert zu zweit ein Beispiel, wo fehlende Typen euch bereits Zeit gekostet haben
  • Welche Datenstrukturen waren beteiligt?
  • Wie hätte eine Typannotation geholfen?
1min
Software- und Web-Engineering I · TH Lübeck
1 Motivation & Kontext
2 JavaScript-Recap
3 Syntax & Einstieg
4 Grundlagen des Typsystems
5 Funktionen & Klassen

Schmerzpunkte an JS erkennen

Software- und Web-Engineering I · TH Lübeck
Was können wir bereits aus JavaScript?
  • Variablen mit var, let, const und grundlegende Scoping-Regeln
  • First-Class Functions, Arrow Functions, Promises
  • DOM-Manipulation, Fetch API, Event Loop Grundverständnis
React npm Node.js
Logos: https://upload.wikimedia.org/
Software- und Web-Engineering I · TH Lübeck
Dynamische Typen – Fluch & Segen
  • JavaScript erlaubt spontane Typwechsel (Numbers, Strings, Objects)
  • Flexibel für Prototyping, aber riskant bei Teamarbeit
  • Beispiel von impliziter Typkonvertierung
console.log('5' - 2); // 3
console.log('5' + 2); // "52"
Wer hat so etwas schon einmal im Debugger gesehen?
Software- und Web-Engineering I · TH Lübeck
Bug-Kategorie: Falsche Parameter
  • Häufig: Funktionen erwarten Zahlen, bekommen aber Strings oder undefined
  • Beispiel aus einer fiktiven Preisberechnung:
function applyDiscount(price, factor) {
  if (!factor) {
    return price; // vergisst, dass factor=0 gültig wäre
  }
  return price * factor;
}
Ohne Typen/Null-Checks schwer im Review zu erkennen
Wie hättet ihr factor abgesichert?
Software- und Web-Engineering I · TH Lübeck
Bug-Kategorie: Optionale Felder
  • Frontend-Formulare liefern teils unvollständige Objekte
  • Beispiel: API-Antwort ohne email
const user = JSON.parse(payload);
console.log(user.email.toLowerCase()); // Runtime-Error wenn email fehlt
Typen könnten email? markieren und sofort warnen
Software- und Web-Engineering I · TH Lübeck
Typfehler
  • Wo habt ihr zuletzt Typfehler erlebt?
  • Welche Daten flossen durch die Funktion?
  • Warum blieb der Fehler bis in die Runtime verborgen?
Software- und Web-Engineering I · TH Lübeck
Bug finden
const items = ['3', '4', '5'];
const sum = items.reduce((acc, value) => acc + value);
console.log(sum);
  • Überlegen, was geloggt wird und warum
  • Welche Information fehlt dem Editor, um uns zu warnen?
1 min
Software- und Web-Engineering I · TH Lübeck
1 Motivation & Kontext
2 JavaScript-Recap
3 Syntax & Einstieg
4 Grundlagen des Typsystems
5 Funktionen & Klassen

Wie hängt TS mit JS zusammen?

Software- und Web-Engineering I · TH Lübeck
.ts vs. .js
  • .ts-Dateien werden zu .js transpiliert
  • TypeScript bietet Typprüfung, die im Browser nicht sichtbar ist
  • JS-Features bleiben gültig – TS ist ein Superset
TS-Kreis mit JS-Kern, Pfeil über TS Compiler zu JS: Browser can execute
Quelle: https://miro.medium.com/v2/resize:fit:1400/1*86CeLAAdbeCcOWUDIurkhg.png
Software- und Web-Engineering I · TH Lübeck
Projekt-Setup in 3 Schritten
  • 1. npm init -y – Grundgerüst anlegen
  • 2. npm install typescript --save-dev
  • 3. npx tsc --init – erzeugt tsconfig.json
  • Tipp: npx tsc --watch für Live-Feedback
TypeScript Playground
TypeScript Playground
https://www.typescriptlang.org/play
Software- und Web-Engineering I · TH Lübeck
Wichtige tsconfig-Flags
  • target: Welcher JS-Standard wird erzeugt?
  • module: CommonJS vs. ES Modules
  • strict: Aktiviert strenge Typprüfungen
  • esModuleInterop: erleichtert Import von CommonJS-Paketen
{
  "compilerOptions": {
    "target": "es2016",
    "module": "commonjs",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  }
}
Software- und Web-Engineering I · TH Lübeck
Demo: JS-Funktion typisieren
  • Schritt 1: Datei in sum.ts umbenennen
  • Schritt 2: Parameter annotieren
// sum.js
function sum(a, b) {
  return a + b;
}

const result = sum('3', 4);
// sum.ts
function sum(a: number, b: number): number {
  return a + b;
}

const result = sum('3', 4); // Compilerfehler
Editor zeigt roten Unterstrich + Typ-Hinweis
Software- und Web-Engineering I · TH Lübeck
Live-Kompilierung verstehen
  • npx tsc test.ts erzeugt test.js
  • Ergebnisdatei zeigt reines JavaScript, keine Typinformationen mehr
  • Erinnerung: Typsicherheit existiert nur zur Compile-Zeit
// test.ts
const str: string = "Hello, TS!";
const x: number = 42;
// test.js
var str = "Hello, TS!";
var x = 42;
Software- und Web-Engineering I · TH Lübeck
1 Motivation & Kontext
2 JavaScript-Recap
3 Syntax & Einstieg
4 Grundlagen des Typsystems
5 Funktionen & Klassen

Grundlagen des Typsystems

Software- und Web-Engineering I · TH Lübeck
Überblick: Bausteine
  • TypeScript erweitert JavaScript um ein statisches, strukturelles Typsystem
  • Werteformen beschreiben, Vertrauen in Datenflüsse erhöhen
  • Typdefinitionen existieren nur beim Entwickeln und Kompilieren
Typhierarchie: unknown über any, darunter boolean, number, bigint, string, symbol, object mit Array/Function, dazu void, undefined, null, never
Software- und Web-Engineering I · TH Lübeck
Primitive Typen
  • string, number, boolean, null, undefined, bigint, symbol
  • Literaltypen präzisieren Werte
    • type Status = 'open' | 'done'
let counter: number = 0;
const status: 'open' = 'open';
let flag: boolean | undefined;
Hinweis: any deaktiviert Schutz – sparsam einsetzen
Software- und Web-Engineering I · TH Lübeck
Arrays & Tupel
  • Arrays typisieren mit string[] oder Array<string>
  • Tupel fixieren Länge & Positionstypen
const tags: string[] = ['ts', 'lecture'];
const point: [number, number] = [12, 8];
point[0] = 5;      // ok
point.push(9);     // Fehler in strict mode
Wann würdet ihr ein Tupel statt eines Objekts nutzen?
Software- und Web-Engineering I · TH Lübeck
Union vs. Intersection
  • Union (|): Wert darf mehrere Formen haben
  • Intersection (&): Kombination mehrerer Typanforderungen
type ID = string | number;
type Timestamped = { createdAt: Date } & { updatedAt: Date };

function printId(id: ID) {
  console.log(id.toString());
}
Software- und Web-Engineering I · TH Lübeck
Interfaces vs. Type Aliases
  • Interfaces für Objektformen mit möglicher Erweiterung
  • Type Aliases flexibler (Unions, Primitives, Mapped Types)
  • extends vs. & zur Kombination
interface User {
  id: number;
  name: string;
}

type Admin = User & { role: 'admin' };
Software- und Web-Engineering I · TH Lübeck
Formular-Interface entwerfen
  • Ziel: Interface für ein Frontend-Formular “Team-Anmeldung”
  • Felder: teamName, members (Array von Strings), contactEmail?
  • Status-Feld als Literal-Union ('draft' | 'submitted')
  • Optional: Tupel [string, number] für preferredSlot
3 min
Software- und Web-Engineering I · TH Lübeck
interface TeamRegistrationForm {
  teamName: string;
  members: string[];
  contactEmail?: string;
  status: 'draft' | 'submitted';
  preferredSlot?: [string, number];
}
Software- und Web-Engineering I · TH Lübeck
1 Motivation & Kontext
2 JavaScript-Recap
3 Syntax & Einstieg
4 Grundlagen des Typsystems
5 Funktionen & Klassen

… und ein Exkurs zu Generics

Software- und Web-Engineering I · TH Lübeck
Überblick
  • Bausteine für komplexere Module:
    • Funktionen kapseln Logik
    • Klassen modellieren Strukturen
    • Generics halten Code wiederverwendbar
  • Ziel: Typsicherheit ohne Doppelarbeit erreichen
Software- und Web-Engineering I · TH Lübeck
Funktionen typisieren
  • Parameter und Rückgabewerte explizit annotieren
  • Optional mit ?, Defaultwerte behalten Typen
  • Rest-Parameter nutzen ...args: number[]
function greet(name: string, title?: string): string {
  return `Hallo ${title ?? ''} ${name}`.trim();
}

const sum = (...values: number[]): number =>
  values.reduce((acc, value) => acc + value, 0);
Vorteil: Editor kennt Signaturen und Autocomplete
Software- und Web-Engineering I · TH Lübeck
Funktionen als Typen
  • Function Type Aliases beschreiben Callback-Signaturen
  • Überprüfbar für Events, Promises, Higher-Order Functions
type Comparator<T> = (a: T, b: T) => number;

const compareUsers: Comparator<{ id: number }> = (a, b) => a.id - b.id;
Wie stellt ihr sicher, dass ein Callback wirklich async ist?
Software- und Web-Engineering I · TH Lübeck
Klassenbasics
  • Klassen deklarieren Felder, Konstruktoren und Methoden
  • Modifier: public, private, protected, readonly
interface Notifiable {
  notify(message: string): void;
}

class User implements Notifiable {
  constructor(private readonly id: number, public name: string) {}

  notify(message: string): void {
    console.log(`[${this.id}] ${message}`);
  }
}
Software- und Web-Engineering I · TH Lübeck
Vererbung & abstrakte Klassen
  • extends ermöglicht Code-Sharing
  • abstract Klassen definieren Pflichtmethoden
abstract class BaseService {
  abstract execute(): Promise<void>;

  log(msg: string) {
    console.log(`[Service] ${msg}`);
  }
}

class MailService extends BaseService {
  async execute() {
    this.log('Sende Mail');
  }
}
Software- und Web-Engineering I · TH Lübeck
Einstieg in Generics
  • Generics = Platzhalter für Typen (<T>)
  • Nutzen, wenn sich Logik nicht auf einen konkreten Typ festlegen soll
  • Alltägliche Beispiele: Promise<T>, Array<T>, Map<K, V>
function wrapInArray<T>(value: T): T[] {
  return [value];
}

const names = wrapInArray('Ada');
const flags = wrapInArray(true);
Software- und Web-Engineering I · TH Lübeck
Generische Constraints
  • Einschränken mit extends, damit bestimmte Eigenschaften vorhanden sind
interface Identifiable {
  id: string;
}

function findById<T extends Identifiable>(items: T[], id: string): T | undefined {
  return items.find(item => item.id === id);
}
Ohne Constraint könnte item.id nicht genutzt werden
Software- und Web-Engineering I · TH Lübeck
Generics in Klassen & Repositories
interface Identifiable {
  id: string;
}

class Repository<T extends Identifiable> {
  private items = new Map<string, T>();

  add(item: T) {
    this.items.set(item.id, item);
  }

  getAll(): T[] {
    return [...this.items.values()];
  }
}
Software- und Web-Engineering I · TH Lübeck
Generics & Refactoring
  • Welche Stellen im Projekt profitieren am meisten von Generics?
  • Wo können Generics zu kompliziert werden?
Software- und Web-Engineering I · TH Lübeck
Generische Ergebnisstruktur
  • Entwerft einen generischen Typen Result
  • Objekt mit generischer data oder error als String
  • Definition mit Union + Generics
4 min
Software- und Web-Engineering I · TH Lübeck
Generische Ergebnisstruktur
  • Entwerft einen generischen Typen Result
  • Objekt mit generischer data oder error als String
  • Definition mit Union + Generics
type Result<T> = { data: T } | { error: string };
4 min
Software- und Web-Engineering I · TH Lübeck

- Einstieg: heute TypeScript, der typisierte Aufsatz auf JavaScript - Nicht auf dem Titel verweilen

- Kernbotschaft: TS ist kein Bruch, sondern ein Aufsatz auf JS - Drop-In Replacement: bestehende Codebasis kann Datei fuer Datei migriert werden

- Sektionsauftakt: warum TypeScript, Bezug zum Semesterprojekt - Roadmap kurz zeigen: fuenf Stationen heute, Teil 2 folgt

- Bezug zum Projekt herstellen: stabile Web-App im Team - Betonen: TS ersetzt nichts, es ergaenzt das vorhandene JS-Wissen

- Gemeinsame Typbasis: Domaenenmodell und API-Vertrag (REST-Vorlesung) als TS-Interfaces im Front-End - Back-End ist Spring Boot (Java); TS-Back-Ends nur als Ausblick erwaehnen

- Links JS: Bug bleibt unsichtbar bis zur Laufzeit - Rechts TS: der Editor warnt sofort beim Aufruf mit String - Frage: "Wo wuerde dieser Bug in eurem Projekt auftauchen?"

- Kurze Partneruebung, danach 1-2 Beitraege im Plenum einsammeln - Erwartung: jeder hat schon Zeit durch Typfehler verloren

- Kurzer Rueckblick auf JavaScript, dann typische Bug-Kategorien

- Vorwissen aus den JS-Vorlesungen aktivieren - Kurz nachfragen, wer schon mit Node/npm gearbeitet hat

- Beispiel laut durchgehen: minus konvertiert zu Zahl, plus konkateniert - Kurzes Stimmungsbild einholen, nicht lange diskutieren

- Falsy-Falle zeigen: factor=0 ist gueltig, wird aber wie fehlend behandelt - Kurz Antworten sammeln (=== undefined, Default-Parameter, Typen)

- JSON.parse liefert any: der Editor kann nicht warnen - Mit optionalem Feld email? wuerde der Zugriff sofort angemeckert

- Konkrete Stories aus dem Plenum sammeln - Schluesselwoerter am Whiteboard notieren, spaeter darauf zurueckkommen

- Erwartete Loesung: "345" wird geloggt, String-Konkatenation statt Summe - Ueberleitung: TypeScript haette den Typ string[] erkannt

- Jetzt praktisch: Dateiendungen, Setup, erster Compiler-Lauf

- Grafik: Browser kann TS nicht ausfuehren, erst der Compiler macht JS daraus - Superset-Kreis zeigen: JS steckt komplett in TS drin

- Drei Befehle live zeigen oder zumindest vorlesen - Playground als Null-Setup-Alternative fuer schnelle Experimente

- Nur die vier wichtigsten Flags erklaeren, Rest ist Nachschlagewerk - strict: true als Empfehlung fuer das Projekt aussprechen

- Idealerweise live im Editor vorfuehren: umbenennen, annotieren, Fehler sehen - Der Aufruf mit '3' wird sofort rot unterstrichen

- Typannotationen verschwinden beim Kompilieren komplett - Zur Laufzeit gibt es keine Typpruefung mehr, nur zur Compile-Zeit

- Kernkapitel: die Bausteine des Typsystems der Reihe nach

- Hierarchie nur grob zeigen: unknown ganz oben, never ganz unten - Strukturell: entscheidend ist die Form der Werte, nicht der Name

- Primitive kurz durchgehen, Literaltypen als Besonderheit hervorheben - any-Warnung deutlich machen: Schutz faellt komplett weg

- Tupel: feste Laenge und feste Typen pro Position - Frage kurz diskutieren (z.B. Koordinaten, Key-Value-Paare)

- Union = oder, Intersection = und - Vorgriff: Union braucht spaeter Narrowing (Teil 2)

- Faustregel: reine Objektformen als interface, alles andere als type - Keine Glaubensfrage daraus machen, beides ist ok

- Stillarbeit oder Zweiergruppen, danach Vergleich - Bonusfrage: Interface oder Type Alias, wofuer entscheidet ihr euch?

- Musterloesung zeigen, Abweichungen der Teams kurz besprechen - Optionale Felder und Literal-Union hervorheben

- Letzte Sektion heute: Funktionen, Klassen und der Einstieg in Generics

- Roter Faden der Sektion: drei Bausteine, ein Ziel - "Ohne Doppelarbeit" = kein Copy-Paste pro Typ

- Optionaler Parameter title? und Rest-Parameter im Beispiel zeigen - Autocomplete-Vorteil betonen: Signatur ist Dokumentation

- Funktionstypen als eigenstaendige Typen begreifen - Antwort auf die Frage: Rueckgabetyp Promise<...> im Alias erzwingen

- Parameter-Properties im Konstruktor hervorheben (private readonly id) - implements: Interface als Vertrag fuer die Klasse

- abstract execute() muss von der Kindklasse implementiert werden - Hinweis: nur ueberschreiben, was noetig ist, sonst waechst Komplexitaet

- T wird beim Aufruf automatisch bestimmt: string[] bzw. boolean[] - Bekannte Generics nennen, die alle schon benutzt haben (Promise, Array)

- extends Identifiable garantiert, dass jedes T eine id hat - Ohne Constraint kennt der Compiler item.id nicht

- Ein Repository fuer User, Task, Board ohne Copy & Paste - Bruecke zum Projekt: solche Bausteine kommen in jedem Backend vor

- Kurzer Austausch (2 Minuten), ein Beispiel im Plenum teilen lassen - Auch die Grenze ansprechen: zu viel Generik wird unlesbar

- Pair Programming, danach kurze Demo eines Teams - Hinweis geben: Union aus zwei Objektformen

- Musterloesung: eine Zeile, Union aus data- und error-Form - Ausblick: dieses Result-Muster kommt in Teil 2 beim Narrowing wieder