This commit is contained in:
Philippe Torrel
2026-07-29 14:39:16 +02:00
parent 6bf3c2c7c5
commit 14c22e4b18
71 changed files with 5266 additions and 106 deletions

View File

@@ -486,7 +486,7 @@ Projekte + weiteres Modul einbinden
**Inhalt:**
- Typescript Annotationen
- Primitive, Object, Union Types
- Primitive Types, Object, Union Types
- type statement vs interface
- Type Assertion with as and <>
- Typescript "more Types"

View File

@@ -0,0 +1,10 @@
(() => {
// src/main.ts
{
const processData = (input) => {
return input * 2;
};
let result = processData(100);
console.log(result);
}
})();

View File

@@ -1,6 +1,8 @@
const processData = (input: any): any => {
return input * 2;
};
{
const processData = (input: number): number => {
return input * 2;
};
let result = processData('100');
console.log(result);
let result = processData(100);
console.log(result);
}

View File

@@ -1,7 +1,22 @@
// TODO: Deklariere eine Variable, um den Namen einer Person zu speichern, und gib ihn explizit als String ein.
{
// [x] : Deklariere eine Variable, um den Namen einer Person zu speichern, und gib ihn explizit als String ein.
const john: string = 'John';
// TODO: Deklariere eine Funktion, die zwei Parameter, firstName und lastName, beide vom Typ String, benötigt und einen verketteten vollständigen Namen (ebenfalls vom Typ String) zurückgibt.
// [x]: Deklariere eine Funktion, die zwei Parameter, firstName und lastName, beide vom Typ String, benötigt und einen verketteten vollständigen Namen (ebenfalls vom Typ String) zurückgibt.
const greet = (firstName: string, lastName: string): string => {
const greet: string = `Hello ${firstName} ${lastName}`;
return greet;
};
// TODO: Deklariere eine weitere Funktion, die die Summe des Zahlenfeldes [10, 20, 30] berechnet. Diese Funktion sollte das Zahlenfeld als Eingabe haben und die Summe der Zahlen zurückgeben (der Rückgabetyp sollte Zahl sein).
// [x]: Deklariere eine weitere Funktion, die die Summe des Zahlenfeldes [10, 20, 30] berechnet. Diese Funktion sollte das Zahlenfeld als Eingabe haben und die Summe der Zahlen zurückgeben (der Rückgabetyp sollte Zahl sein).
const sumNumbers = (numbers: number[]): number => {
return numbers.reduce((sum, num) => sum + num, 0);
};
// TODO: Verwende die Funktionen und Variablen, um eine Nachricht zu protokollieren, die den vollständigen Namen einer Person und die Summe einer Reihe von Zahlen enthält.
// [x]: Verwende die Funktionen und Variablen, um eine Nachricht zu protokollieren, die den vollständigen Namen einer Person und die Summe einer Reihe von Zahlen enthält.
const name: string = greet('John', 'Wick');
const sum: number = sumNumbers([10, 20, 30]);
console.log(`Gruß: ${name}, Summe des Arrays: ${sum}`);
}

View File

@@ -1,6 +1,18 @@
// Step 1: Define the Book object type
type Book = {
title: string;
author: string;
yearPublished?: number;
};
// Step 2: Implement the function to print book details
const printBookDetails = (book: Book): void => {
if (typeof book.yearPublished !== 'undefined') {
console.log(`Title: ${book.title} Author: ${book.author} Year Published: ${book.yearPublished}`);
} else {
console.log(`Title: ${book.title} Author: ${book.author} Year Published: Not Available`);
}
};
// Test cases to verify your code implementation (comment out the code below to remove the initial errors)
printBookDetails({ title: 'The TypeScript Handbook', author: 'Dan Vanderkam' });

View File

@@ -1,12 +1,32 @@
{
const processInput = (input: string | number | boolean): string | number => {
// TODO: Implement logic here to handle different types of input
// [x]: Implement logic here to handle different types of input
// - If the input is a string, return the string in uppercase
// - If the input is a number, return the square of the number
// - If the input is a boolean, return "Yes" if true, otherwise "No"
if (typeof input === 'string') {
return input.toUpperCase();
// - If the input is a number, return the square of the number
} else if (typeof input === 'number') {
return input * input;
// - If the input is a boolean, return "Yes" if true, otherwise "No"
} else if (typeof input === 'boolean') {
return input ? 'Yes' : 'No';
}
// switch (typeof input) {
// case 'string':
// return input.toUpperCase();
// case 'number':
// return input ** 2;
// case 'boolean':
// return input ? 'Yes' : 'No';
// default:
// return 'ungültiger Datentyp';
// }
// Placeholder return statement to be replaced
return input;
return 'Ungültiger Parameter "input"';
};
// Test cases to verify your code implementation (comment out the code below to remove the initial errors)

View File

@@ -1,26 +1,50 @@
// Step 1: Define a type alias 'Person' for an object type with the following properties:
// - name: a string
// - age: a number
// - isActive: a boolean
{
// Step 1: Define a type alias 'Person' for an object type with the following properties:
type Person = {
name: string;
age: number;
isActive: boolean;
};
// Step 2: Define a type alias 'ResponseStatus' for a union type that includes the following string literals:
// - "success"
// - "failure"
// - "pending"
// Step 2: Define a type alias 'ResponseStatus' for a union type that includes the following string literals:
type ResponseStatus = 'success' | 'failure' | 'pending';
// Step 3: Implement a function 'printPersonDetails' that takes a parameter of type 'Person'
// - The function should print out the person's name, age, and activity status ("Active" or "Inactive" based on the isActive property).
// Step 3: Implement a function 'printPersonDetails' that takes a parameter of type 'Person'
// - The function should print out the person's name, age, and activity status ("Active" or "Inactive" based on the isActive property).
// Step 4: Implement a function 'handleResponse' that takes a parameter of type 'ResponseStatus'
// - The function should print different messages based on the value of the 'ResponseStatus' ("Operation successful", "Operation failed", "Operation pending").
const printPersonDetails = (person: Person): void => {
const status = person.isActive ? 'Active' : 'Inactive';
// Test cases to verify your code implementation (comment out the code below to remove the initial errors)
console.log(`Name: ${person.name}, Age: ${person.age}, ${status}`);
};
// Create an object of type 'Person' and pass it to 'printPersonDetails'
const person = { name: 'Alice', age: 30, isActive: true };
printPersonDetails(person); // => Name: Alice, Age: 30, Status: Active
// Step 4: Implement a function 'handleResponse' that takes a parameter of type 'ResponseStatus'
// - The function should print different messages based on the value of the 'ResponseStatus' ("Operation successful", "Operation failed", "Operation pending").
const handleResponse = (responseStatus: ResponseStatus): void => {
switch (responseStatus) {
case 'success':
console.log('Operation successfull');
break;
case 'failure':
console.log('Operation failed');
break;
case 'pending':
console.log('Operation pending');
break;
default:
console.error('error');
}
};
// Pass different 'ResponseStatus' values to 'handleResponse'
handleResponse('success'); // => "Operation successful"
handleResponse('failure'); // => "Operation failed"
handleResponse('pending'); // => "Operation pending"
// Test cases to verify your code implementation (comment out the code below to remove the initial errors)
// Create an object of type 'Person' and pass it to 'printPersonDetails'
const person = { name: 'Alice', age: 30, isActive: true };
printPersonDetails(person); // => Name: Alice, Age: 30, Status: Active
printPersonDetails({ name: 'John', age: 80, isActive: false }); // => Name: John, Age: 80, Inactive
// Pass different 'ResponseStatus' values to 'handleResponse'
handleResponse('success'); // => "Operation successful"
handleResponse('failure'); // => "Operation failed"
handleResponse('pending'); // => "Operation pending"
}

View File

@@ -1,27 +1,51 @@
// Step 1: Define an interface 'Person' with the following properties:
// - name: a string
// - age: a number
{
// Step 1: Define an interface 'Person' with the following properties:
// - name: a string
// - age: a number
// Step 2: Extend the 'Person' interface to create an 'Employee' interface with an additional property:
// - employeeId: a number
interface Person {
name: string;
age: number;
}
// Step 3: Implement a function 'printEmployeeDetails' that takes a parameter of type 'Employee'
// - The function should print out the employee's name, age, and employeeId.
// Step 2: Extend the 'Person' interface to create an 'Employee' interface with an additional property:
// - employeeId: a number
interface Employee extends Person {
employeeId: number;
}
// Step 4: Declare the 'Display' interface with a property:
// - resolution: a string
// Step 3: Implement a function 'printEmployeeDetails' that takes a parameter of type 'Employee'
// - The function should print out the employee's name, age, and employeeId.
// Step 5: Add a new property 'size: number' to the 'Display' interface using declaration merging
const printEmployeeDetails = (emp: Employee) => {
console.log(`Name: ${emp.name}, Age: ${emp.age}, eID: ${emp.employeeId}`);
};
// Step 6: Implement a function 'printDisplayDetails' that takes a parameter of type 'Display'
// - The function should print out the display's resolution and size.
// Step 4: Declare the 'Display' interface with a property:
// - resolution: a string
interface Display {
resolution: string;
}
// Test cases to verify your code implementation (comment out the code below to remove the initial errors)
// Step 5: Add a new property 'size: number' to the 'Display' interface using declaration merging
interface Display {
size: number;
}
// Create an 'Employee' object and pass it to 'printEmployeeDetails'
const employee = { name: 'Bob', age: 40, employeeId: 12345 };
printEmployeeDetails(employee); // => Name: Bob, Age: 40, Employee ID: 12345
// Step 6: Implement a function 'printDisplayDetails' that takes a parameter of type 'Display'
// - The function should print out the display's resolution and size.
const printDisplayDetails = (display: Display) => {
const { resolution, size } = display;
console.log(`Resoultion: ${resolution}, Size: ${size}`);
};
// Create a 'Display' object and pass it to 'printDisplayDetails'
const display = { resolution: '4K', size: 27 };
printDisplayDetails(display); // => Resolution: 4K, Size: 27
// Test cases to verify your code implementation (comment out the code below to remove the initial errors)
// Create an 'Employee' object and pass it to 'printEmployeeDetails'
const employee = { name: 'Bob', age: 40, employeeId: 12345 };
printEmployeeDetails(employee); // => Name: Bob, Age: 40, Employee ID: 12345
// Create a 'Display' object and pass it to 'printDisplayDetails'
const display = { resolution: '4K', size: 27 };
printDisplayDetails(display); // => Resolution: 4K, Size: 27
}

View File

@@ -1,34 +1,56 @@
// [ ] Step 1: Create an object 'mysteryObject' with a property 'info' that holds a string.
// - The object should be of type 'unknown'.
{
// [x] Step 1: Create an object 'mysteryObject' with a property 'info' that holds a string.
// - The object should be of type 'unknown'.
const mysteryObject: unknown = {
info: 'Holding string',
};
// [ ] Step 2: Use a type assertion to assert that 'mysteryObject' is of type '{ info: string }'.
// [x] Step 2: Use a type assertion to assert that 'mysteryObject' is of type '{ info: string }'.
const typedMysteryObject = mysteryObject as { info: string };
// [ ] Step 3: Access the 'info' property and assign a new string to it.
// [x] Step 3: Access the 'info' property and assign a new string to it.
typedMysteryObject.info = 'A new String';
// [ ] Step 4: Define a custom type 'ComplexObject' with a method 'compute' that returns a string.
// [x] Step 4: Define a custom type 'ComplexObject' with a method 'compute' that returns a string.
type ComplexObject = {
compute: () => string;
};
// [ ] Step 5: Create an object 'basicObject' with a method 'compute'.
// - The method should return a string "Basic Computation".
// [x] Step 5: Create an object 'basicObject' with a method 'compute'.
// - The method should return a string "Basic Computation".
const basicObject = {
// compute: () => {
// return 'Basic Computation';
// },
compute() {
return 'Basic Computation';
},
};
// [ ] Step 6: Use a two-step type assertion to assert that 'basicObject' is of type 'ComplexObject'.
// [x] Step 6: Use a two-step type assertion to assert that 'basicObject' is of type 'ComplexObject'.
const complexObject = basicObject as unknown as ComplexObject;
// TODO: two-step type assertion Wann?
// [ ] Step 7: Call the 'compute' method on 'basicObject' and log the result.
// [x] Step 7: Call the 'compute' method on 'basicObject' and log the result.
console.log('Step 7 basicObject: ', basicObject.compute());
console.log('Step 7 complexObject: ', complexObject.compute());
// Test cases to verify your code implementation (comment out the code below to remove the initial errors)
// Test cases to verify your code implementation (comment out the code below to remove the initial errors)
// Verify that 'info' was correctly accessed and modified
console.log('Updated info:', typedMysteryObject.info); // => "Updated Info"
// Verify that 'info' was correctly accessed and modified
console.log('Updated info:', typedMysteryObject.info); // => "Updated Info"
// Verify that 'compute' method of 'complexObject' returns the expected result
if (complexObject.compute() === 'Basic Computation') {
console.log('compute method returned the expected result.');
} else {
console.error('compute method did not return the expected result.');
}
// Verify 'info' type compatibility
if (typeof typedMysteryObject.info === 'string') {
console.log('info property is of type string.');
} else {
console.error('info property is not of type string.');
// Verify that 'compute' method of 'complexObject' returns the expected result
if (complexObject.compute() === 'Basic Computation') {
console.log('compute method returned the expected result.');
} else {
console.error('compute method did not return the expected result.');
}
// Verify 'info' type compatibility
if (typeof typedMysteryObject.info === 'string') {
console.log('info property is of type string.');
} else {
console.error('info property is not of type string.');
}
}

View File

@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Übung 11: Arbeiten mit Literal Types in TypeScript</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.7/dist/css/bootstrap.min.css" rel="stylesheet" />
<script src="assets/js/bundle.js" defer></script>
</head>
<body>
<main>
<div class="container py-5">
<div class="alert alert-primary">
<h2>Übung 11: Arbeiten mit Literal Types in TypeScript</h2>
<p>
In dieser Übung übst du die Verwendung von Literal Types in TypeScript, um spezifischere und kontrollierte
Typen für deine Variablen und Funktionsparameter zu erstellen. Du wirst Funktionen definieren, die bestimmte
String-, numerische und boolesche Literal Types akzeptieren und sicherstellen, dass nur die erlaubten Werte
an diese Funktionen übergeben werden können.
</p>
</div>
</div>
</main>
</body>
</html>

View File

@@ -0,0 +1,13 @@
{
"name": "10_assertions",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"ts": "npx esbuild src/main.ts --watch --bundle --outfile=assets/js/bundle.js --loader:.ts=ts"
},
"keywords": [],
"author": "",
"license": "ISC",
"type": "commonjs"
}

View File

@@ -0,0 +1,30 @@
// [ ] Step 1: Create a function 'setStatus' that accepts a string literal type parameter 'status'.
// - The 'status' can only be "success", "error", or "loading".
// - The function should log the status to the console.
// [ ] Step 2: Create a function 'rateExperience' that accepts a numeric literal type parameter 'rating'.
// - The 'rating' can only be 1, 2, 3, 4, or 5.
// - The function should return a message indicating the rating.
// [ ] Step 3: Create a function 'togglePower' that accepts a boolean literal type parameter 'state'.
// - The 'state' can only be true or false.
// - The function should return a message indicating whether the power is ON or OFF.
// [ ] Step 4: Test the functions with valid and invalid values to ensure the correct behavior and type safety.
// Test cases (students should verify that these work as expected)
// Test 'setStatus' function
setStatus('success'); // OK
setStatus('error'); // OK
setStatus('complete'); // Error: Argument of type '"complete"' is not assignable to parameter of type '"success" | "error" | "loading"'.
// Test 'rateExperience' function
console.log(rateExperience(5)); // => "You rated the experience as 5"
console.log(rateExperience(3)); // => "You rated the experience as 3"
console.log(rateExperience(6)); // Error: Argument of type '6' is not assignable to parameter of type '1 | 2 | 3 | 4 | 5'.
// Test 'togglePower' function
console.log(togglePower(true)); // => "Power is ON"
console.log(togglePower(false)); // => "Power is OFF"
console.log(togglePower('on')); // Error: Argument of type '"on"' is not assignable to parameter of type 'true | false'.

View File

@@ -0,0 +1,45 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Übung 12: Implementiere eine Type Guard Funktion</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" />
<script src="assets/js/bundle.js" defer></script>
</head>
<body>
<main>
<div class="container py-5">
<div class="alert alert-primary">
<h2>Übung 12: Implementiere eine Type Guard Funktion</h2>
<p>
Schreibe eine TypeScript-Funktion namens <code>formatInput</code>, die einen Parameter
<code>input</code> akzeptiert, der vom Typ <code>number</code>, <code>string</code> oder
<code>boolean</code>
sein kann. Die Funktion sollte einen formatierten String zurückgeben, der auf dem Typ der Eingabe basiert:
</p>
<ul class="list">
<li>
Wenn <code>input</code> eine <code>number</code> ist, gibst du die Zahl multipliziert mit
<code>100</code> als <code>string</code> zurück.
</li>
<li>
Wenn <code>input</code> ein <code>string</code> ist, wird
<code>string</code>
in Kleinbuchstaben zurückgegeben.
</li>
<li>
Wenn <code>input</code> eine <code>boolean</code> ist, gib "Yes" zurück, wenn <code>input</code> eine
<code>true</code> ist, und "No", wenn <code>input</code> eine <code>false</code> ist.
</li>
</ul>
<p>
Verwende den <code>typeof</code> Operator, um die Typen innerhalb der Funktion einzugrenzen.
<br />
Kopiere den Code unten und füge ihn ein, um deine Implementierung zu testen.
</p>
</div>
</div>
</main>
</body>
</html>

View File

@@ -0,0 +1,13 @@
{
"name": "12_type-guard",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"ts": "npx esbuild src/main.ts --watch --bundle --outfile=assets/js/bundle.js --loader:.ts=ts"
},
"keywords": [],
"author": "",
"license": "ISC",
"type": "commonjs"
}

View File

@@ -0,0 +1,19 @@
console.log(formatInput(0.5)); // => "50"
console.log(formatInput(12)); // => "1200"
console.log(formatInput('Hello')); // => "hello"
console.log(formatInput('WORLD')); // => "world"
console.log(formatInput(true)); // => "Yes"
console.log(formatInput(false)); // => "No"
// Übung 12: Implementiere eine Type Guard Funktion
// Schreibe eine TypeScript-Funktion namens formatInput, die einen Parameter input akzeptiert, der vom Typ number, string oder boolean sein kann. Die Funktion sollte einen formatierten String zurückgeben, der auf dem Typ der Eingabe basiert:
// Wenn input eine number ist, gibst du die Zahl multipliziert mit 100 als string zurück.
// Wenn input ein string ist, wird string in Kleinbuchstaben zurückgegeben.
// Wenn input eine boolean ist, gib "Yes" zurück, wenn input eine true ist, und "No", wenn input eine false ist.
// Verwende den typeof Operator, um die Typen innerhalb der Funktion einzugrenzen.
// Kopiere den Code unten und füge ihn ein, um deine Implementierung zu testen.

View File

@@ -0,0 +1,31 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Übung 13: Implementierung der Truthiness Narrowing in einer Funktion</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" />
<script src="assets/js/bundle.js" defer></script>
</head>
<body>
<main>
<div class="container py-5">
<div class="alert alert-primary">
<h2>Übung 13: Implementierung der Truthiness Narrowing in einer Funktion</h2>
<p>
Schreibe eine TypeScript-Funktion namens <code>displayStatus</code>, die einen Parameter
<code>status</code> akzeptiert, der ein <code>string</code>, <code>null</code> oder
<code>undefined</code> sein kann. Die Funktion sollte:
</p>
<ul class="list">
<li>Wenn <code>status</code> truthy ist, wird die Zeichenfolge "Status: ", verkettet mit Status.</li>
<li>
Wenn <code>status</code> fehlerhaft ist, wird die Zeichenfolge "No status available." zurückgegeben.
</li>
</ul>
<p>Verwende die Truthiness Narrowing, um zu prüfen, ob der Status truthy oder falsch ist.</p>
</div>
</div>
</main>
</body>
</html>

View File

@@ -0,0 +1,13 @@
{
"name": "13_narrowing",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"ts": "npx esbuild src/main.ts --watch --bundle --outfile=assets/js/bundle.js --loader:.ts=ts"
},
"keywords": [],
"author": "",
"license": "ISC",
"type": "commonjs"
}

View File

@@ -0,0 +1,17 @@
console.log(displayStatus('Active')); // => "Status: Active"
console.log(displayStatus('Pending')); // => "Status: Pending"
console.log(displayStatus(null)); // => "No status available."
console.log(displayStatus(undefined)); // => "No status available."
console.log(displayStatus('')); // => "No status available."
// Übung 13: Implementierung der Truthiness Narrowing in einer Funktion
// Schreibe eine TypeScript-Funktion namens displayStatus, die einen Parameter status akzeptiert, der ein string, null oder undefined sein kann. Die Funktion sollte:
// Wenn status truthy ist, wird die Zeichenfolge "Status: ", verkettet mit Status.
// Wenn status fehlerhaft ist, wird die Zeichenfolge "No status available." zurückgegeben.
// Verwende die Truthiness Narrowing, um zu prüfen, ob der Status truthy oder falsch ist.
// Kopiere den Code unten und füge ihn ein, um deine Implementierung zu testen.
// // Kopiere den Code unten und füge ihn ein, um deine Implementierung zu testen.

View File

@@ -0,0 +1,34 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Übung 14: Equality Narrowing in einer Funktion implementieren</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" />
<script src="assets/js/bundle.js" defer></script>
</head>
<body>
<main>
<div class="container py-5">
<div class="alert alert-primary">
<h2>Übung 14: Equality Narrowing in einer Funktion implementieren</h2>
<p>
Gegeben ist eine unvollständige Funktion <code>analyzeInput</code><br />
Vervollständige die Funktion analyzeInput so, dass sie zurückgegeben wird:
</p>
<ul class="list">
<li>"Input is exactly true" wenn input === true.</li>
<li>"Input is exactly false" wenn input === false.</li>
<li>"Input is zero" wenn input === 0.</li>
<li>"Input is a positive number" wenn input eine Zahl größer als null ist.</li>
<li>"Input is a negative number" wenn input eine Zahl kleiner als null ist.</li>
<li>"Input is the string 'hello'" wenn input === "hello".</li>
<li>"Input is another string" wenn input irgendein anderer String ist.</li>
<li>"Unknown input" andernfalls.</li>
</ul>
<p>Verwende Equality- und Vergleichsoperatoren, um den Typ und den Wert der Eingabe einzugrenzen.</p>
</div>
</div>
</main>
</body>
</html>

View File

@@ -0,0 +1,13 @@
{
"name": "14_narrowing-equality",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"ts": "npx esbuild src/main.ts --watch --bundle --outfile=assets/js/bundle.js --loader:.ts=ts"
},
"keywords": [],
"author": "",
"license": "ISC",
"type": "commonjs"
}

View File

@@ -0,0 +1,35 @@
const analyzeInput = (input: string | number | boolean): string => {
// Your code here
};
console.log(analyzeInput(true)); // => "Input is exactly true"
console.log(analyzeInput(false)); // => "Input is exactly false"
console.log(analyzeInput(0)); // => "Input is zero"
console.log(analyzeInput(42)); // => "Input is a positive number"
console.log(analyzeInput(-7)); // => "Input is a negative number"
console.log(analyzeInput('hello')); // => "Input is the string 'hello'"
console.log(analyzeInput('world')); // => "Input is another string"
console.log(analyzeInput('')); // => "Input is another string"
console.log(analyzeInput(undefined)); // => "Unknown input"
console.log(analyzeInput(null)); // => "Unknown input"
// Übung 14: Equality Narrowing in einer Funktion implementieren
// Vervollständige die Funktion analyzeInput so, dass sie zurückgegeben wird:
// "Input is exactly true" wenn input === true.
// "Input is exactly false" wenn input === false.
// "Input is zero" wenn input === 0.
// "Input is a positive number" wenn input eine Zahl größer als null ist.
// "Input is a negative number" wenn input eine Zahl kleiner als null ist.
// "Input is the string 'hello'" wenn input === "hello".
// "Input is another string" wenn input irgendein anderer String ist.
// "Unknown input" andernfalls.
// Verwende Equality- und Vergleichsoperatoren, um den Typ und den Wert der Eingabe einzugrenzen.

View File

@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Übung 15: Verwendung des in-Operators zur Type Narrowing in TypeScript</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" />
<script src="assets/js/bundle.js" defer></script>
</head>
<body>
<main>
<div class="container py-5">
<div class="alert alert-primary">
<h2>Übung 15: Verwendung des in-Operators zur Type Narrowing in TypeScript</h2>
<p>
Erstelle eine TypeScript-Funktion mit dem Namen <code>play</code>, die einen Parameter vom Typ
<code>Guitar | Piano</code> annimmt. Der Typ <code>Guitar</code> hat eine Methode <code>strum</code>, und
der Typ Piano hat eine Methode <code>pressKeys</code>.
</p>
<p>
In der Funktion <code>play</code> verwendest du den Operator <code>in</code>, um festzustellen, ob das
übergebene instrument ein <code>Guitar</code> oder ein <code>Piano</code> ist, und rufst dann die
entsprechende Methode auf. Achte darauf, dass deine Funktion beide Typen richtig behandelt.
</p>
</div>
</div>
</main>
</body>
</html>

View File

@@ -0,0 +1,13 @@
{
"name": "15_narrowing-in-operator",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"ts": "npx esbuild src/main.ts --watch --bundle --outfile=assets/js/bundle.js --loader:.ts=ts"
},
"keywords": [],
"author": "",
"license": "ISC",
"type": "commonjs"
}

View File

@@ -0,0 +1,14 @@
type Guitar = { strum: () => void };
type Piano = { pressKeys: () => void };
const play = (instrument: Guitar | Piano) => {
// Your code here
};
// Create guitar instance
// Create piano instance
// Call functions
play(guitar); // => "Strumming the guitar!"
play(piano); // => "Pressing piano keys!"

View File

@@ -0,0 +1,44 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Übung 16: Type Narrowing mit Zuweisungsoperationen</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" />
<script src="assets/js/bundle.js" defer></script>
</head>
<body>
<main>
<div class="container py-5">
<div class="alert alert-primary">
<h2>Übung 16: Type Narrowing mit Zuweisungsoperationen</h2>
<p>
In dieser Übung arbeitest du mit TypeScripts Features zur Type Narrowing durch Zuweisungsoperationen. Du
definierst eine Variable mit einem Union Type <code>(string | number | boolean)</code> und demonstrierst,
wie TypeScript den Typ dynamisch auf Basis der zugewiesenen Werte einschränkt.
</p>
<p>
Du wirst auch eine Funktion implementieren, die einen Union Type Parameter akzeptiert und diesen korrekt
behandelt, indem du die TypeScript-Funktionen fürs Type Narrowing nutzt.
</p>
<h4>Anweisungen:</h4>
<ol class="list">
<li>
Schreibe eine Funktion handleValue, die einen <code>string | number | boolean</code> Parameter annimmt und
je nach Typ des Arguments ein anderes Verhalten protokolliert.
<ul class="list">
<li>Wenn es eine <code>string</code> ist, protokolliere die Version in Großbuchstaben.</li>
<li>Wenn es sich um eine <code>number</code> handelt, logge ihren Wert multipliziert mit 2.</li>
<li>
Wenn es eine <code>boolean</code> ist, protokolliere "It's true!" oder "It's false!". Verwende einen
ternären Operator.
</li>
</ul>
</li>
<li>Teste die Funktion mit verschiedenen Eingaben.</li>
</ol>
</div>
</div>
</main>
</body>
</html>

View File

@@ -0,0 +1,13 @@
{
"name": "16_narrowing-zuweisung",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"ts": "npx esbuild src/main.ts --watch --bundle --outfile=assets/js/bundle.js --loader:.ts=ts"
},
"keywords": [],
"author": "",
"license": "ISC",
"type": "commonjs"
}

View File

@@ -0,0 +1,25 @@
// Test handleValue with different inputs
handleValue('hello'); // => "HELLO"
handleValue('TypeScript'); // => "TYPESCRIPT"
handleValue(21); // => 42
handleValue(50); // => 100
handleValue(false); // => "It's false!"
handleValue(true); // => "It's true!"
// Übung 16: Type Narrowing mit Zuweisungsoperationen
// In dieser Übung arbeitest du mit TypeScripts Features zur Type Narrowing durch Zuweisungsoperationen. Du definierst eine Variable mit einem Union Type (string | number | boolean) und demonstrierst, wie TypeScript den Typ dynamisch auf Basis der zugewiesenen Werte einschränkt.
// Du wirst auch eine Funktion implementieren, die einen Union Type Parameter akzeptiert und diesen korrekt behandelt, indem du die TypeScript-Funktionen fürs Type Narrowing nutzt.
// Anweisungen:
// 1Schreibe eine Funktion handleValue, die einen string | number | boolean Parameter annimmt und je nach Typ des Arguments ein anderes Verhalten protokolliert.
// Wenn es eine string ist, protokolliere die Version in Großbuchstaben.
// Wenn es sich um eine number handelt, logge ihren Wert multipliziert mit 2.
// Wenn es eine boolean ist, protokolliere "It's true!" oder "It's false!". Verwende einen ternären Operator.
// 2Teste die Funktion mit verschiedenen Eingaben.

View File

@@ -0,0 +1,48 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Übung 17: Kontrollflussanalyse und Type Narrowing</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" />
<script src="assets/js/bundle.js" defer></script>
</head>
<body>
<main>
<div class="container py-5">
<div class="alert alert-primary">
<h2>Übung 17: Kontrollflussanalyse und Type Narrowing</h2>
<p>
In dieser Übung erstellst du eine Funktion, die einen Union Type Parameter akzeptiert und demonstriert, wie
TypeScript automatisch eine Type Narrowing basierend auf dem Kontrollfluss durchführt.
</p>
<p>
Du wirst Bedingungen implementieren, um verschiedene Typen zu behandeln und je nach Typ der Eingabe
unterschiedliche Ergebnisse zurückzugeben. Ziel ist es, die Verwendung der TypeScript Kontrollflussanalyse
zu üben, um Typsicherheit ohne unnötiges Type-Checking zu gewährleisten.
</p>
<h4>Anweisungen:</h4>
<ol class="list">
<li>
Erstelle eine Funktion handleInput, die einen Parameter vom Typ string | number | boolean | null
akzeptiert.
</li>
<li>
Verwende innerhalb der Funktion die Blöcke if, else if und else, um verschiedene Typen zu behandeln:
<ul class="list">
<li>Wenn die input null ist, gibst du "No value provided" zurück.</li>
<li>Wenn die input eine boolean ist, wird "True" oder "False" zurückgegeben.</li>
<li>Wenn input eine string ist, wird die Großbuchstabenversion der Zeichenkette zurückgegeben.</li>
<li>Wenn input eine number ist, wird das Quadrat der Zahl zurückgegeben.</li>
</ul>
</li>
<li>
Teste die Funktion mit verschiedenen Eingaben, um zu überprüfen, ob TypeScript die Typen korrekt
eingrenzt.
</li>
</ol>
</div>
</div>
</main>
</body>
</html>

View File

@@ -0,0 +1,13 @@
{
"name": "17_narrowing-kontrollfluss",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"ts": "npx esbuild src/main.ts --watch --bundle --outfile=assets/js/bundle.js --loader:.ts=ts"
},
"keywords": [],
"author": "",
"license": "ISC",
"type": "commonjs"
}

View File

@@ -0,0 +1,27 @@
// Test cases
console.log(handleInput(null)); // => "No value provided"
console.log(handleInput(true)); // => "True"
console.log(handleInput('hello')); // => "HELLO"
console.log(handleInput(5)); // => 25
// Übung 17: Kontrollflussanalyse und Type Narrowing
// In dieser Übung erstellst du eine Funktion, die einen Union Type Parameter akzeptiert und demonstriert, wie TypeScript automatisch eine Type Narrowing basierend auf dem Kontrollfluss durchführt.
// Du wirst Bedingungen implementieren, um verschiedene Typen zu behandeln und je nach Typ der Eingabe unterschiedliche Ergebnisse zurückzugeben. Ziel ist es, die Verwendung der TypeScript Kontrollflussanalyse zu üben, um Typsicherheit ohne unnötiges Type-Checking zu gewährleisten.
// Anweisungen:
// 1 Erstelle eine Funktion handleInput, die einen Parameter vom Typ string | number | boolean | null akzeptiert.
// 2 Verwende innerhalb der Funktion die Blöcke if, else if und else, um verschiedene Typen zu behandeln:
// Wenn die input null ist, gibst du "No value provided" zurück.
// Wenn die input eine boolean ist, wird "True" oder "False" zurückgegeben.
// Wenn input eine string ist, wird die Großbuchstabenversion der Zeichenkette zurückgegeben.
// Wenn input eine number ist, wird das Quadrat der Zahl zurückgegeben.
// 3 Teste die Funktion mit verschiedenen Eingaben, um zu überprüfen, ob TypeScript die Typen korrekt eingrenzt.

View File

@@ -0,0 +1,50 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Übung 18: Type Predicates implementieren</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" />
<script src="assets/js/bundle.js" defer></script>
</head>
<body>
<main>
<div class="container py-5">
<div class="alert alert-primary">
<h2>Übung 18: Type Predicates implementieren</h2>
<p>
In dieser Aufgabe definierst du zwei verschiedene Typen und implementierst eine benutzerdefinierte Predicate
Function, um zwischen ihnen zu unterscheiden. Dann benutzt du diese Funktion, um verschiedene Objekte in
einem Array zu filtern und zu behandeln.
</p>
<h4>Anweisungen:</h4>
<ol class="list">
<li>
Definiere zwei Typen, Car und Truck, wobei:
<ul>
<li>Car hat eine Methode drive().</li>
<li>Truck hat eine Methode loadCargo().</li>
</ul>
</li>
<li>
Erstelle eine Type Predicate Funktion isCar, um zu prüfen, ob ein bestimmtes Fahrzeug ein Car ist und eine
Fahrfunktion hat. Hinweis: .drive !== undefined.
</li>
<li>
Implementiere eine Funktion handleVehicle, die einen Parameter vom Typ Car | Truck akzeptiert:
<ul class="list">
<li>Wenn das Fahrzeug ein Car ist, rufe drive() an.</li>
<li>Wenn das Fahrzeug ein Truck ist, rufe loadCargo() an.</li>
</ul>
</li>
<li>
Erstelle ein Array von Car | Truck Objekten und filtere nur die Autos mit dem isCar Predicate heraus.
</li>
<li>Teste deine Funktionen mit verschiedenen Eingaben.</li>
</ol>
</div>
</div>
</main>
</body>
</html>

View File

@@ -0,0 +1,13 @@
{
"name": "18_type-predicates",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"ts": "npx esbuild src/main.ts --watch --bundle --outfile=assets/js/bundle.js --loader:.ts=ts"
},
"keywords": [],
"author": "",
"license": "ISC",
"type": "commonjs"
}

View File

@@ -0,0 +1,30 @@
// Test the filtered array
const cars = vehicles.filter(isCar);
cars.forEach((car) => car.drive()); // => "Car driving"
// Test handleVehicle with both Car and Truck
handleVehicle({ drive: () => console.log('Car driving') }); // => "Car driving"
handleVehicle({ loadCargo: () => console.log('Truck loading cargo') }); // => "Truck loading cargo"
// Übung 18: Type Predicates implementieren
// In dieser Aufgabe definierst du zwei verschiedene Typen und implementierst eine benutzerdefinierte Predicate Function, um zwischen ihnen zu unterscheiden. Dann benutzt du diese Funktion, um verschiedene Objekte in einem Array zu filtern und zu behandeln.
// Anweisungen:
// 1 Definiere zwei Typen, Car und Truck, wobei:
// Car hat eine Methode drive().
// Truck hat eine Methode loadCargo().
// 2 Erstelle eine Type Predicate Funktion isCar, um zu prüfen, ob ein bestimmtes Fahrzeug ein Car ist und eine Fahrfunktion hat. Hinweis: .drive !== undefined.
// 3 Implementiere eine Funktion handleVehicle, die einen Parameter vom Typ Car | Truck akzeptiert:
// Wenn das Fahrzeug ein Car ist, rufe drive() an.
// Wenn das Fahrzeug ein Truck ist, rufe loadCargo() an.
// 4 Erstelle ein Array von Car | Truck Objekten und filtere nur die Autos mit dem isCar Predicate heraus.
// 5 Teste deine Funktionen mit verschiedenen Eingaben.

View File

@@ -0,0 +1,50 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Übung 19: Arbeiten mit Function Type Expressions</title>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.7/dist/css/bootstrap.min.css"
rel="stylesheet" />
<script src="assets/js/bundle.js" defer></script>
</head>
<body>
<main>
<div class="container py-5">
<div class="alert alert-primary">
<h2>Übung 19: Arbeiten mit Function Type Expressions</h2>
<p>
In dieser Aufgabe schreibst du eine Funktion, die andere Funktionen
als Parameter akzeptiert und Logik basierend auf diesen Function
Type Expressions implementiert.
</p>
<h4>Anweisungen:</h4>
<ol class="list">
<li>
Definiere einen Type Alias <code>MathOperation</code> für eine
Funktion, die zwei <code>numbers</code> als Parameter nimmt und
einen <code>number</code> zurückgibt.
</li>
<li>
Implementiere eine Funktion <code>calculate</code>, die eine
Funktion vom Typ <code>MathOperation</code> und zwei
<code>numbers</code>
annimmt und die Funktion auf die Zahlen anwendet.
</li>
<li>
Erstelle zwei neue Funktionen, <code>add</code> und
<code>multiply</code>, die der Signatur
<code>MathOperation</code> entsprechen.
</li>
<li>
Teste alle Funktionen, indem du geeignete Argumente übergibst und
die Ergebnisse protokollierst.
</li>
</ol>
</div>
</div>
</main>
</body>
</html>

View File

@@ -0,0 +1,13 @@
{
"name": "19_fn-typausdruecke",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"ts": "npx esbuild src/main.ts --watch --bundle --outfile=assets/js/bundle.js --loader:.ts=ts"
},
"keywords": [],
"author": "",
"license": "ISC",
"type": "commonjs"
}

View File

@@ -0,0 +1,17 @@
// Test cases
console.log(calculate(add, 10, 5)); // => 15
console.log(calculate(multiply, 10, 5)); // => 50
// Übung 19: Arbeiten mit Function Type Expressions
// In dieser Aufgabe schreibst du eine Funktion, die andere Funktionen als Parameter akzeptiert und Logik basierend auf diesen Function Type Expressions implementiert.
// Anweisungen:
// 1 Definiere einen Type Alias MathOperation für eine Funktion, die zwei numbers als Parameter nimmt und einen number zurückgibt.
// 2 Implementiere eine Funktion calculate, die eine Funktion vom Typ MathOperation und zwei numbers annimmt und die Funktion auf die Zahlen anwendet.
// 3 Erstelle zwei neue Funktionen, add und multiply, die der Signatur MathOperation entsprechen.
// 4 Teste alle Funktionen, indem du geeignete Argumente übergibst und die Ergebnisse protokollierst.

Binary file not shown.

View File

@@ -1,10 +1,121 @@
(() => {
// src/CreateBtn.ts
var defaultOpts = {
classes: [],
iconName: "circle",
showLabel: false,
label: "No Label",
clickHandler: () => {
console.log("no action");
}
};
var CreateButton = (options = defaultOpts) => {
const {
classes = defaultOpts.classes,
iconName = defaultOpts.iconName,
showLabel = defaultOpts.showLabel,
label = defaultOpts.label,
clickHandler = defaultOpts.clickHandler
} = options;
const btn = document.createElement("button");
const icon = document.createElement("i");
const span = document.createElement("span");
btn.classList.add("btn", "me-2", "btn-sm", ...classes);
if (Array.isArray(iconName)) {
icon.classList.add("fas", ...iconName.map((icon2) => `fa-${icon2}`));
} else {
icon.classList.add("fas", `fa-${iconName}`);
}
!showLabel && span.classList.add("visually-hidden");
span.textContent = label;
btn.addEventListener("click", clickHandler);
btn.appendChild(icon);
btn.appendChild(span);
return btn;
};
var CreateBtn_default = CreateButton;
// src/main.ts
(() => {
const DOM = {
output: document.querySelector(".output")
};
if (!DOM.output) return;
const init = () => {
renderButtons();
};
const renderButtons = () => {
const btn1 = CreateBtn_default({
classes: ["btn-primary", "me-2"],
iconName: "plus",
label: "Hinzuf\xFCgen",
clickHandler: () => alert("Button 1 geklickt!")
});
const btn2 = CreateBtn_default({
classes: ["btn-success", "me-2"],
iconName: "check",
label: "Speichern",
clickHandler: () => console.log("Gespeichert")
});
const btn3 = CreateBtn_default({
classes: ["btn-warning", "me-2"],
iconName: "pen",
label: "Bearbeiten",
clickHandler: () => console.log("Bearbeiten gestartet")
});
const btn4 = CreateBtn_default({
classes: ["btn-danger"],
iconName: "trash",
label: "L\xF6schen",
clickHandler: () => console.log("Gel\xF6scht")
});
const btn5 = CreateBtn_default({
classes: ["btn-danger"],
showLabel: true,
label: "Default",
clickHandler: () => console.log("Gel\xF6scht")
});
const btn6 = CreateBtn_default();
const btn7 = CreateBtn_default({
classes: ["btn-warning"],
iconName: ["compass", "spin"],
label: "compass",
clickHandler: () => console.log("Test")
});
const btnOption1 = CreateBtn_default({
classes: ["btn-secondary"],
iconName: "angle-up",
label: "LabelButton1",
clickHandler: () => {
console.log("Button 1 clicki");
}
});
const btnOption2 = CreateBtn_default({
classes: ["btn-primary"],
iconName: "check",
showLabel: true,
label: "LabelButton2"
// clickHandler: () => {
// console.log('Button 2 clicki');
// },
});
const btnOption3 = CreateBtn_default({
classes: ["btn-dark"],
iconName: "user",
label: "LabelButton3",
clickHandler: () => {
console.log("Button 3 clicki");
}
});
const btnOption4 = CreateBtn_default({
classes: ["btn-light", "btn-outline-primary"],
iconName: "pen",
label: "LabelButton4",
clickHandler: () => {
console.log("Button 4 clicki");
}
});
DOM.output.append(btn1, btn2, btn3, btn4, btn5, btn6, btn7, btnOption1, btnOption2, btnOption3, btnOption4);
};
init();
})();

View File

@@ -5,6 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>CreateBtn als Modul</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.0.1/css/all.min.css" />
<script src="assets/js/bundle.js" defer></script>
</head>
<body>

File diff suppressed because it is too large Load Diff

View File

@@ -4,10 +4,15 @@
"description": "",
"main": "index.js",
"scripts": {
"ts": "npx esbuild src/main.ts --watch --bundle --outfile=assets/js/bundle.js --loader:.ts=ts"
"ts": "npx esbuild src/main.ts --watch --bundle --outfile=assets/js/bundle.js --loader:.ts=ts",
"server": "npx http-server -p 3000 -c-1",
"start": "run-p server ts"
},
"keywords": [],
"author": "",
"license": "ISC",
"type": "module"
"type": "module",
"devDependencies": {
"npm-run-all": "^4.1.5"
}
}

View File

@@ -1,26 +1,46 @@
interface Options {}
export interface Options {
classes: string[];
iconName?: string | string[];
label: string;
showLabel?: boolean;
clickHandler?: (e: PointerEvent) => void; // so kann bei nichtangabe des clickhandlers, der def wert der funktion CreateButton verwendet werden
}
const CreateButton = (options = {}) => {
const defaultOpts: Options = {
classes: [],
iconName: 'circle',
showLabel: false,
label: 'No Label',
clickHandler: () => {
console.log('no action');
},
};
const CreateButton = (options: Options = defaultOpts): HTMLButtonElement => {
// Destructuring
const {
classes = [],
iconName = 'circle',
label = 'No Label',
clickHandler = () => {
console.log('no action');
},
classes = defaultOpts.classes,
iconName = defaultOpts.iconName,
showLabel = defaultOpts.showLabel,
label = defaultOpts.label,
clickHandler = defaultOpts.clickHandler,
} = options;
const btn = document.createElement('button');
const icon = document.createElement('i');
const span = document.createElement('span');
btn.classList.add('btn', 'btn-sm', ...classes);
icon.classList.add('fas', `fa-${iconName}`);
span.classList.add('visually-hidden');
btn.classList.add('btn', 'me-2', 'btn-sm', ...classes);
if (Array.isArray(iconName)) {
// ['circle', 'spin'] -> wird zu classList.add('fas', 'fa-circle', 'fa-spin')
icon.classList.add('fas', ...iconName.map((icon) => `fa-${icon}`));
} else {
icon.classList.add('fas', `fa-${iconName}`);
}
!showLabel && span.classList.add('visually-hidden');
span.textContent = label;
btn.addEventListener('click', clickHandler);
btn.addEventListener('click', clickHandler as EventListener);
// btn.append(icon,span)
btn.appendChild(icon);
btn.appendChild(span);

View File

@@ -1,4 +1,4 @@
import CreateBtn from './CreateBtn.ts';
import CreateButton from './CreateBtn.js'; // Hinweis: In der Regel nutzt man hier .js als Dateiendung für Modul-Imports im Build-Prozess
(() => {
// === DOM & VARS =======
@@ -6,14 +6,93 @@ import CreateBtn from './CreateBtn.ts';
output: document.querySelector('.output') as HTMLDivElement,
};
if (!DOM.output) return;
// === INIT =============
const init = () => {};
// === EVENTHANDLER =====
// === XHR/FETCH ========
const init = () => {
renderButtons();
};
// === FUNCTIONS ========
const renderButtons = () => {
const btn1 = CreateButton({
classes: ['btn-primary', 'me-2'],
iconName: 'plus',
label: 'Hinzufügen',
clickHandler: () => alert('Button 1 geklickt!'),
});
const btn2 = CreateButton({
classes: ['btn-success', 'me-2'],
iconName: 'check',
label: 'Speichern',
clickHandler: () => console.log('Gespeichert'),
});
const btn3 = CreateButton({
classes: ['btn-warning', 'me-2'],
iconName: 'pen',
label: 'Bearbeiten',
clickHandler: () => console.log('Bearbeiten gestartet'),
});
const btn4 = CreateButton({
classes: ['btn-danger'],
iconName: 'trash',
label: 'Löschen',
clickHandler: () => console.log('Gelöscht'),
});
const btn5 = CreateButton({
classes: ['btn-danger'],
showLabel: true,
label: 'Default',
clickHandler: () => console.log('Gelöscht'),
});
const btn6 = CreateButton();
const btn7 = CreateButton({
classes: ['btn-warning'],
iconName: ['compass', 'spin'],
label: 'compass',
clickHandler: () => console.log('Test'),
});
const btnOption1 = CreateButton({
classes: ['btn-secondary'],
iconName: 'angle-up',
label: 'LabelButton1',
clickHandler: () => {
console.log('Button 1 clicki');
},
});
const btnOption2 = CreateButton({
classes: ['btn-primary'],
iconName: 'check',
showLabel: true,
label: 'LabelButton2',
// clickHandler: () => {
// console.log('Button 2 clicki');
// },
});
const btnOption3 = CreateButton({
classes: ['btn-dark'],
iconName: 'user',
label: 'LabelButton3',
clickHandler: () => {
console.log('Button 3 clicki');
},
});
const btnOption4 = CreateButton({
classes: ['btn-light', 'btn-outline-primary'],
iconName: 'pen',
label: 'LabelButton4',
clickHandler: () => {
console.log('Button 4 clicki');
},
});
// DOM.output.textContent = '';
DOM.output.append(btn1, btn2, btn3, btn4, btn5, btn6, btn7, btnOption1, btnOption2, btnOption3, btnOption4);
};
init();
})();

Binary file not shown.

View File

@@ -10,12 +10,16 @@
let isLearning: boolean = true;
let age: number = 41; // RECOMMENDED explicit type annotation
let age2 = 30; // type inference - 'age' is inferred to be a number
let age2 = 30; // type inference - 'age2' is inferred to be a number
// Array
let scores: number[] = [10, 20, 30, 40];
let moreScores: Array<number> = [50, 60, 70];
// nicht Grundtypen
let lisItems: Node[] = Array.from(document.querySelectorAll('li'));
let lisItems2: NodeListOf<HTMLLIElement> = document.querySelectorAll('li');
// Unions mit Array
const mixedScores: (number | string)[] = [10, 20, 30, '40'];
const moreMixedScores: Array<number | string> = [50, '60', 70];
@@ -28,14 +32,14 @@
// randomValue.doSomething(); // No error in ts, even though `doSomething` doesn't exist.
// randomValue(); // Uncaught TypeError: randomValue.doSomething is not a function
// const $on = (elOrAr: Node | Node[], type: string, fn: EventListener) => {
// if (Array.isArray(elOrAr)) {
// elOrAr.forEach((ae) => $on(ae, type, fn));
// } else {
// elOrAr.addEventListener(type, fn);
// }
// return elOrAr;
// };
const $on = (elOrAr: Node | Node[], type: string, fn: EventListener) => {
if (Array.isArray(elOrAr)) {
elOrAr.forEach((ae) => $on(ae, type, fn));
} else {
elOrAr.addEventListener(type, fn);
}
return elOrAr;
};
const $ = (qs: string) => document.querySelector(qs) as Node;
const $$ = (qs: string): Node[] => Array.from(document.querySelectorAll(qs));

Binary file not shown.

After

Width:  |  Height:  |  Size: 333 KiB

View File

@@ -0,0 +1,33 @@
(() => {
// src/01_type-interface-extends.ts
{
const printVehicleInfo = (vehicle) => {
console.log(`Make: ${vehicle.make}`);
console.log(`Model: ${vehicle.model}`);
console.log(`Year: ${vehicle.year}`);
};
printVehicleInfo({ make: "Honda", model: "Civic", year: 2020 });
const employee = {
name: "John Doe",
age: 30,
employeeId: 123
};
console.log(employee.name);
console.log(employee.age);
console.log(employee.employeeId);
const employee2 = {
name: "Jack Russel",
age: 30,
employeeId: 123
};
console.log(employee2.name);
console.log(employee2.age);
console.log(employee2.employeeId);
const monitor = {
resolution: "1080p",
size: 24
};
console.log(monitor.resolution);
console.log(monitor.size);
}
})();

View File

@@ -0,0 +1,14 @@
(() => {
// src/02_type-as-statement.ts
{
const h1El = document.querySelector("h1");
const headlineElement = document.querySelector("h1");
console.log(h1El);
headlineElement.style.color = "tomato";
const pEl = document.querySelector("p");
const paragraphEl = document.querySelector("p");
console.log(pEl?.offsetHeight, paragraphEl.offsetHeight);
const customElem = document.getElementById("custom-element");
customElem.customMethod();
}
})();

View File

@@ -0,0 +1,57 @@
(() => {
// src/03_type-literale.ts
{
let language = "English";
const lang = "English";
console.log(language, lang);
const greeting = "Hello";
const greeting2 = "Hello";
const number = 23;
const number2 = 23;
const setDirection = (direction) => {
console.log(`Moving ${direction}`);
};
setDirection("up");
setDirection("down");
setDirection("left");
setDirection("right");
const evaluateScore = (score) => {
return `You rated the service a ${score}`;
};
evaluateScore(5);
evaluateScore(3);
const draw = (shape) => {
console.log(`Drawing a ${shape.type} with size ${shape.size}`);
};
draw({ type: "circle", size: 10 });
draw({ type: "square", size: 20 });
let Move;
((Move2) => {
Move2["Up"] = "up";
Move2["Down"] = "down";
Move2["Right"] = "right";
Move2["Left"] = "left";
})(Move || (Move = {}));
const setDirection2 = (movement) => {
console.log(`Moving ${movement}`);
};
setDirection2("down" /* Down */);
setDirection2("right" /* Right */);
setDirection2("left" /* Left */);
setDirection2("right" /* Right */);
let Rating;
((Rating2) => {
Rating2[Rating2["One"] = 1] = "One";
Rating2[Rating2["Two"] = 2] = "Two";
Rating2[Rating2["Three"] = 3] = "Three";
Rating2[Rating2["Four"] = 4] = "Four";
Rating2[Rating2["Five"] = 5] = "Five";
})(Rating || (Rating = {}));
const evaluateScore2 = (score) => {
return `You rated the service a ${score}`;
};
evaluateScore2(1 /* One */);
evaluateScore2(5 /* Five */);
evaluateScore2(4 /* Four */);
}
})();

View File

@@ -0,0 +1,25 @@
<!doctype html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>TypeScript - Types</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" />
<!-- <script src="assets/js/01_type-interface-extends.js" defer></script> -->
<!-- <script src="assets/js/02_type-as-statement.js" defer></script> -->
<script src="assets/js/03_type-literale.js" defer></script>
</head>
<body>
<main>
<div class="container py-5">
<h1>TypeScript - Types</h1>
<p>
TypeScript ist eine von Microsoft entwickelte Skriptsprache, die auf den Vorschlägen zum
ECMAScript-6-Standardbasiert und statische Typisierung zu JavaScript hinzufügt. Sprachkonstrukte von
TypeScript, wie Klassen, Vererbung, Module und anonyme Funktionen, wurden auch in ECMAScript 6 übernommen.
</p>
<img src="assets/img/Understand-Typescript.jpg" alt="TypeScript Kreisdiagramm" class="img-thumbnail" />
</div>
</main>
</body>
</html>

View File

@@ -0,0 +1,499 @@
{
"name": "01_ts-types",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "01_ts-types",
"version": "1.0.0",
"devDependencies": {
"esbuild": "^0.28.1"
}
},
"node_modules/@esbuild/aix-ppc64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz",
"integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==",
"cpu": [
"ppc64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"aix"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/android-arm": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz",
"integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/android-arm64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz",
"integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/android-x64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz",
"integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/darwin-arm64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz",
"integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/darwin-x64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz",
"integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/freebsd-arm64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz",
"integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/freebsd-x64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz",
"integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-arm": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz",
"integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-arm64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz",
"integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-ia32": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz",
"integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==",
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-loong64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz",
"integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==",
"cpu": [
"loong64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-mips64el": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz",
"integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==",
"cpu": [
"mips64el"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-ppc64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz",
"integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==",
"cpu": [
"ppc64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-riscv64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz",
"integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==",
"cpu": [
"riscv64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-s390x": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz",
"integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==",
"cpu": [
"s390x"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-x64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz",
"integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/netbsd-arm64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz",
"integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/netbsd-x64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz",
"integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openbsd-arm64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz",
"integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openbsd-x64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz",
"integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openharmony-arm64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz",
"integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"openharmony"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/sunos-x64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz",
"integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"sunos"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-arm64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz",
"integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-ia32": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz",
"integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==",
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-x64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz",
"integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/esbuild": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz",
"integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"bin": {
"esbuild": "bin/esbuild"
},
"engines": {
"node": ">=18"
},
"optionalDependencies": {
"@esbuild/aix-ppc64": "0.28.1",
"@esbuild/android-arm": "0.28.1",
"@esbuild/android-arm64": "0.28.1",
"@esbuild/android-x64": "0.28.1",
"@esbuild/darwin-arm64": "0.28.1",
"@esbuild/darwin-x64": "0.28.1",
"@esbuild/freebsd-arm64": "0.28.1",
"@esbuild/freebsd-x64": "0.28.1",
"@esbuild/linux-arm": "0.28.1",
"@esbuild/linux-arm64": "0.28.1",
"@esbuild/linux-ia32": "0.28.1",
"@esbuild/linux-loong64": "0.28.1",
"@esbuild/linux-mips64el": "0.28.1",
"@esbuild/linux-ppc64": "0.28.1",
"@esbuild/linux-riscv64": "0.28.1",
"@esbuild/linux-s390x": "0.28.1",
"@esbuild/linux-x64": "0.28.1",
"@esbuild/netbsd-arm64": "0.28.1",
"@esbuild/netbsd-x64": "0.28.1",
"@esbuild/openbsd-arm64": "0.28.1",
"@esbuild/openbsd-x64": "0.28.1",
"@esbuild/openharmony-arm64": "0.28.1",
"@esbuild/sunos-x64": "0.28.1",
"@esbuild/win32-arm64": "0.28.1",
"@esbuild/win32-ia32": "0.28.1",
"@esbuild/win32-x64": "0.28.1"
}
}
}
}

View File

@@ -0,0 +1,14 @@
{
"name": "01_ts-types",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"ts": "npx esbuild \"src/*.ts\" --watch --bundle --outdir=\"assets/js\" --loader:.ts=ts"
},
"keywords": [],
"type": "module",
"devDependencies": {
"esbuild": "^0.28.1"
}
}

View File

@@ -0,0 +1,109 @@
// Interfaces - eine leistungsstarke Funktion zur Definition der Form eines Objekts. Ein Interface ermöglicht es dir, die Eigenschaften, die ein Objekt haben soll, zusammen mit ihren Typen festzulegen, was deinen Code lesbarer und einfacher zu pflegen macht.
{
interface Vehicle {
make: string;
model: string;
year: number;
}
const printVehicleInfo = (vehicle: Vehicle) => {
console.log(`Make: ${vehicle.make}`);
console.log(`Model: ${vehicle.model}`);
console.log(`Year: ${vehicle.year}`);
};
printVehicleInfo({ make: 'Honda', model: 'Civic', year: 2020 });
// Object literal may only specify known properties, and 'releaseYear' does not exist in type 'Vehicle'.
// printVehicleInfo({ make: 'Nissan', model: 'Pao', releaseYear: 1984 });
// -----
interface Person {
name: string;
age: number;
}
interface Employee extends Person {
employeeId: number;
}
const employee: Employee = {
name: 'John Doe',
age: 30,
employeeId: 123,
};
console.log(employee.name); // from Person
console.log(employee.age); // from Person
console.log(employee.employeeId); // from Employee
// ----
type Person2 = {
name: string;
age: number;
};
// NOT RECOMMENDED - use interfaces instead
// Erweiterung bei type Objekt mit "&" ampersand
type Employee2 = Person2 & {
employeeId: number;
};
const employee2: Employee2 = {
name: 'Jack Russel',
age: 30,
employeeId: 123,
};
console.log(employee2.name); // from Person
console.log(employee2.age); // from Person
console.log(employee2.employeeId); // from Employee
// ------
interface Display {
resolution: string;
}
// Migration bzw. Erweiterung vom bestehenden Display Interface
interface Display {
size: number;
}
const monitor: Display = {
resolution: '1080p',
size: 24,
};
console.log(monitor.resolution); // => 1080p
console.log(monitor.size); // => 24
// -----
type Display2 = {
resolution: string;
};
// type Display2 = {
// size: number;
// };
// Error: Duplicate identifier 'Display2'.
// ------
// interface für wachsende und komplexe Datenstrukturen. Meistens (global) ausgelagert.
// interface Car {
// make: string;
// model: string;
// year: number;
// };
// type aliases innerhalb von Dokumenten für einfache, feststehende types und unions
type Car = {
make: string;
model: string;
year: number;
};
}

View File

@@ -0,0 +1,30 @@
// Type Assertions verwenden - mit "as" statement festen Datentyp zuweisen
{
const h1El: HTMLHeadingElement | null = document.querySelector('h1');
// selber festgelegt
const headlineElement = document.querySelector('h1') as HTMLHeadingElement;
console.log(h1El);
// h1El?.style?.color = 'tomato';
headlineElement.style.color = 'tomato';
const pEl: HTMLParagraphElement | null = document.querySelector('p');
// selber festgelegt
const paragraphEl = <HTMLParagraphElement>document.querySelector('p');
console.log(pEl?.offsetHeight, paragraphEl.offsetHeight);
interface MyCustomElement extends Node {
customMethod: () => void;
}
// Assume 'Node' is a custom element with a 'customMethod'
const customElem = document.getElementById('custom-element') as unknown as MyCustomElement;
// Now TypeScript understands that 'customElem' is of type 'MyCustomElement'
customElem.customMethod();
}

View File

@@ -0,0 +1,101 @@
// Literalzuweisung - Feste alleinstehende Werte zuweisen
{
let language = 'English'; // TypeScript infers the type of `language` as `string`.
const lang = 'English'; // TypeScript infers the type of `lang` as literal 'English'.
console.log(language, lang);
const greeting = 'Hello'; // inferred as literal 'Hello'
const greeting2: 'Hello' = 'Hello'; // inferred as literal 'Hello'
const number = 23; // inferred as literal 23
const number2: 23 = 23; // inferred as literal 23
// -------
type Direction = 'up' | 'down' | 'left' | 'right';
const setDirection = (direction: Direction): void => {
console.log(`Moving ${direction}`);
};
setDirection('up');
setDirection('down');
setDirection('left');
setDirection('right');
// setDirection('north'); // Argument of type '"north"' is not assignable to parameter of type 'Direction'
// ------
type Score = 1 | 2 | 3 | 4 | 5;
const evaluateScore = (score: Score) => {
return `You rated the service a ${score}`;
};
evaluateScore(5); // OK
evaluateScore(3); // OK
// evaluateScore(6); // Error: Argument of type '6' is not assignable to parameter of type '1 | 2 | 3 | 4 | 5'.
// ------
interface Splide {
type: 'loop' | 'slide' | 'fade';
nav: boolean;
showDots: boolean;
fixedHeight: number | string;
}
interface Shape {
type: 'circle' | 'square';
size: number;
}
const draw = (shape: Shape) => {
console.log(`Drawing a ${shape.type} with size ${shape.size}`);
};
draw({ type: 'circle', size: 10 }); // OK
draw({ type: 'square', size: 20 }); // OK
// draw({ type: 'triangle', size: 15 }); // Error: Type '"triangle"' is not assignable to type '"circle" | "square"'.
// -----
// enum - Enumerationen sind ein spezieller Typ, der eine Liste von konstanten Werten definiert.
// Sie sind nützlich, um eine Gruppe von Werten zu definieren, die eine bestimmte Bedeutung haben.
enum Move {
Up = 'up',
Down = 'down',
Right = 'right',
Left = 'left',
}
const setDirection2 = (movement: Move): void => {
console.log(`Moving ${movement}`);
};
setDirection2(Move.Down);
setDirection2(Move.Right);
setDirection2(Move.Left);
setDirection2(Move.Right);
// ----
enum Rating {
One = 1,
Two = 2,
Three = 3,
Four = 4,
Five = 5,
}
const evaluateScore2 = (score: Rating): string => {
return `You rated the service a ${score}`;
};
evaluateScore2(Rating.One); // OK
evaluateScore2(Rating.Five); // OK
evaluateScore2(Rating.Four); // OK
// evaluateScore2(Rating.Six);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 333 KiB

View File

@@ -0,0 +1,73 @@
(() => {
// src/01_narrowing.ts
{
const displayValue = (value) => {
if (typeof value === "string") {
console.log(value.toUpperCase());
} else {
console.log(value.toFixed(2));
}
};
displayValue("Hello World");
displayValue(19);
const processPadding = (padding, input) => {
if (typeof padding === "number") {
return `${padding * 2}${input}`;
} else {
return `${padding}${input}`;
}
};
processPadding(2, "px");
processPadding("1.5", "rem");
const handleInput = (input) => {
if (typeof input === "boolean") {
return input ? "The value is true!" : "The value is false.";
} else if (typeof input === "number") {
return `The number is ${input * 10}.`;
} else {
return `The string is "${input.toUpperCase()}".`;
}
};
handleInput(true);
handleInput(10);
handleInput("super");
const processNumbers = (numbers) => {
if (Array.isArray(numbers)) {
numbers.forEach((num) => {
console.log(num * 2);
});
}
};
processNumbers([1, 2, 3, 4]);
processNumbers(null);
console.log(typeof []);
console.log(typeof {});
console.log("object");
const displayInfo = (input) => {
if (input !== null && typeof input === "object") {
console.log(input.name);
} else {
console.log(input);
}
};
displayInfo({ name: "ErrorHandler" });
displayInfo("Error");
displayInfo(null);
const processData = (data2) => {
if (typeof data2 === "string") {
console.log(`String value: ${data2.toUpperCase()}`);
} else if (typeof data2 === "number") {
console.log(`Number squared: ${data2 ** 2}`);
} else if (typeof data2 === "boolean") {
console.log(`Boolean value: ${data2 ? "True" : "False"}`);
} else {
console.log("No valid data provided.");
}
};
let data;
processData("Hello");
processData(4);
processData(true);
processData(data);
}
})();

View File

@@ -0,0 +1,38 @@
(() => {
// src/02_truthiness.ts
{
const showMessage = (userCount) => {
return userCount ? `There are ${userCount} users online.` : "No users online.";
};
console.log(showMessage(5));
const printNames = (names) => {
if (names) {
names.forEach((name) => {
console.log(name);
});
} else {
console.log("No names provided.");
}
};
printNames(["Adel", "Ersin", "Andreas", "Kahleel"]);
printNames(null);
const displayInput = (input) => {
if (input) {
console.log(`Input provided: ${input}`);
} else {
console.log("No input provided.");
}
};
displayInput(document.querySelector("h2"));
const multiplyValues = (values, factor) => {
if (!values) {
return void 0;
}
return values.map((value) => value * factor);
};
let numbers;
console.log(multiplyValues([1, 2, 3, 4], 2));
console.log(multiplyValues([], 2));
console.log(multiplyValues(numbers, 2));
}
})();

View File

@@ -0,0 +1,34 @@
(() => {
// src/03_equality.ts
{
const compareValues = (a, b) => {
if (a === b) {
console.log(a.toUpperCase());
console.log(b.toLowerCase());
} else {
console.log(`a is ${a}, b is ${b}`);
}
};
const result = compareValues(1, "1");
console.log(result);
const scaleValue = (container, factor) => {
if (container.value != null) {
container.value *= factor;
}
};
const processInput = (input) => {
if (input !== null) {
if (typeof input === "number") {
console.log(`Number input: ${input}`);
} else {
console.log(`String input: ${input}`);
}
} else {
console.log("No input provided.");
}
};
processInput(23);
processInput("23");
processInput(null);
}
})();

View File

@@ -0,0 +1,32 @@
(() => {
// src/04_in-operator.ts
{
const isCar = (vehicle) => {
return Object.hasOwn(vehicle, "drive");
};
const operate = (vehicle) => {
if ("drive" in vehicle) {
vehicle.drive();
} else {
vehicle.sail();
}
};
const car = { drive: () => console.log("I'm driving") };
const sealander = { sail: () => console.log("I'm sailing") };
operate(car);
operate(sealander);
const move = (entity) => {
if ("walk" in entity) {
entity.walk?.();
} else if ("fly" in entity) {
entity.fly?.();
}
};
const dog = { bark: () => console.log("Woof") };
const bird = { fly: () => console.log("Flying") };
const robot = { walk: () => console.log("Walking") };
move(dog);
move(bird);
move(robot);
}
})();

View File

@@ -0,0 +1,37 @@
(() => {
// src/05_kontrollflussanalyse.ts
{
const processData = (data) => {
if (typeof data === "boolean") {
console.log("Boolean value:", data);
} else if (typeof data === "string") {
console.log("String value:", data.toUpperCase());
} else {
console.log("Number value:", data.toFixed(2));
}
};
processData(true);
processData("hello");
processData(123);
const checkValue = (value) => {
if (typeof value === "string") {
return `String: ${value}`;
}
return `Number: ${value.toFixed(2)}`;
};
console.log(checkValue("hello"));
console.log(checkValue(123));
const describeInput = (input) => {
if (input === null) {
return "No input provided.";
}
if (typeof input === "string") {
return `String input: ${input.toUpperCase()}`;
}
return `Number input: ${input.toFixed(2)}`;
};
console.log(describeInput("hello"));
console.log(describeInput(123));
console.log(describeInput(null));
}
})();

View File

@@ -0,0 +1,26 @@
(() => {
// src/06_type-predicate.ts
{
const isFish = (pet2) => {
return Object.hasOwn(pet2, "swim");
};
const pet = { swim: () => console.log("Is swimming") };
if (isFish(pet)) {
pet.swim();
}
const handlePet = (pet2) => {
if (isFish(pet2)) {
pet2.swim();
} else {
pet2.fly();
}
};
handlePet(pet);
const zoo = [
{ swim: () => console.log("Fish swimming") },
{ fly: () => console.log("Bird flying") }
];
const fishes = zoo.filter(isFish);
fishes.forEach((fish) => fish.swim());
}
})();

View File

@@ -0,0 +1,24 @@
<!doctype html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>TypeScript - Narrowing und Guards</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" />
<!-- <script src="assets/js/01_narrowing.js" defer></script> -->
<script src="assets/js/02_truthiness.js" defer></script>
</head>
<body>
<main>
<div class="container py-5">
<h1>TypeScript - Narrowing und Guards</h1>
<p>
TypeScript ist eine von Microsoft entwickelte Skriptsprache, die auf den Vorschlägen zum
ECMAScript-6-Standardbasiert und statische Typisierung zu JavaScript hinzufügt. Sprachkonstrukte von
TypeScript, wie Klassen, Vererbung, Module und anonyme Funktionen, wurden auch in ECMAScript 6 übernommen.
</p>
<img src="assets/img/Understand-Typescript.jpg" alt="TypeScript Kreisdiagramm" class="img-thumbnail" />
</div>
</main>
</body>
</html>

View File

@@ -0,0 +1,499 @@
{
"name": "01_ts-types",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "01_ts-types",
"version": "1.0.0",
"devDependencies": {
"esbuild": "^0.28.1"
}
},
"node_modules/@esbuild/aix-ppc64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz",
"integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==",
"cpu": [
"ppc64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"aix"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/android-arm": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz",
"integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/android-arm64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz",
"integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/android-x64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz",
"integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/darwin-arm64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz",
"integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/darwin-x64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz",
"integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/freebsd-arm64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz",
"integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/freebsd-x64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz",
"integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-arm": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz",
"integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==",
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-arm64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz",
"integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-ia32": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz",
"integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==",
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-loong64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz",
"integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==",
"cpu": [
"loong64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-mips64el": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz",
"integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==",
"cpu": [
"mips64el"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-ppc64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz",
"integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==",
"cpu": [
"ppc64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-riscv64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz",
"integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==",
"cpu": [
"riscv64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-s390x": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz",
"integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==",
"cpu": [
"s390x"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/linux-x64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz",
"integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/netbsd-arm64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz",
"integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/netbsd-x64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz",
"integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openbsd-arm64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz",
"integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openbsd-x64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz",
"integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/openharmony-arm64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz",
"integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"openharmony"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/sunos-x64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz",
"integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"sunos"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-arm64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz",
"integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-ia32": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz",
"integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==",
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/@esbuild/win32-x64": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz",
"integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=18"
}
},
"node_modules/esbuild": {
"version": "0.28.1",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz",
"integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"bin": {
"esbuild": "bin/esbuild"
},
"engines": {
"node": ">=18"
},
"optionalDependencies": {
"@esbuild/aix-ppc64": "0.28.1",
"@esbuild/android-arm": "0.28.1",
"@esbuild/android-arm64": "0.28.1",
"@esbuild/android-x64": "0.28.1",
"@esbuild/darwin-arm64": "0.28.1",
"@esbuild/darwin-x64": "0.28.1",
"@esbuild/freebsd-arm64": "0.28.1",
"@esbuild/freebsd-x64": "0.28.1",
"@esbuild/linux-arm": "0.28.1",
"@esbuild/linux-arm64": "0.28.1",
"@esbuild/linux-ia32": "0.28.1",
"@esbuild/linux-loong64": "0.28.1",
"@esbuild/linux-mips64el": "0.28.1",
"@esbuild/linux-ppc64": "0.28.1",
"@esbuild/linux-riscv64": "0.28.1",
"@esbuild/linux-s390x": "0.28.1",
"@esbuild/linux-x64": "0.28.1",
"@esbuild/netbsd-arm64": "0.28.1",
"@esbuild/netbsd-x64": "0.28.1",
"@esbuild/openbsd-arm64": "0.28.1",
"@esbuild/openbsd-x64": "0.28.1",
"@esbuild/openharmony-arm64": "0.28.1",
"@esbuild/sunos-x64": "0.28.1",
"@esbuild/win32-arm64": "0.28.1",
"@esbuild/win32-ia32": "0.28.1",
"@esbuild/win32-x64": "0.28.1"
}
}
}
}

View File

@@ -0,0 +1,14 @@
{
"name": "01_ts-types",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"ts": "npx esbuild \"src/*.ts\" --watch --bundle --outdir=\"assets/js\" --loader:.ts=ts"
},
"keywords": [],
"type": "module",
"devDependencies": {
"esbuild": "^0.28.1"
}
}

View File

@@ -0,0 +1,98 @@
// Narrowing - Mit Narrowing kann TypeScript innerhalb eines Codeblocks auf einen bestimmten Typ "eingrenzen", sodass du typspezifische Methoden sicher verwenden kannst.
{
const displayValue = (value: string | number): void => {
if (typeof value === 'string') {
// Type Guard: typeof value === "string"
// Narrowing: 'value' is now of type 'string'
console.log(value.toUpperCase());
} else {
// Narrowing: 'value' is now of type 'number'
console.log(value.toFixed(2));
}
};
displayValue('Hello World'); // => 'HELLO WORLD'
displayValue(19); // => '19.00'
// -------
const processPadding = (padding: number | string, input: string): string => {
if (typeof padding === 'number') {
// Here, padding is confirmed to be a number
return `${padding * 2}${input}`;
} else {
// Here, padding is confirmed to be a string
return `${padding}${input}`;
}
};
processPadding(2, 'px'); // => '4px'
processPadding('1.5', 'rem'); //=> '1.5rem'
// --------
const handleInput = (input: boolean | number | string): string => {
// Narrowing
if (typeof input === 'boolean') {
return input ? 'The value is true!' : 'The value is false.';
} else if (typeof input === 'number') {
return `The number is ${input * 10}.`;
} else {
return `The string is "${input.toUpperCase()}".`;
}
};
handleInput(true); // => 'The value is true!'
handleInput(10); // => 'The number is 100'
handleInput('super'); // => 'The string is super'
// --------
const processNumbers = (numbers: number[] | null): void => {
// Narrowing - Eingrenzung des Datentyps
// if (numbers !== null && typeof numbers === 'object') {
if (Array.isArray(numbers)) {
numbers.forEach((num) => {
console.log(num * 2);
});
}
};
processNumbers([1, 2, 3, 4]); // => 2 4 6 8
processNumbers(null);
// -------
console.log(typeof []); // => 'object'
console.log(typeof {}); // => 'object'
console.log(typeof null); // => 'object'
const displayInfo = (input: string | { name: string } | null) => {
if (input !== null && typeof input === 'object') {
console.log(input.name); // Error: Object is possibly 'null'
} else {
console.log(input);
}
};
displayInfo({ name: 'ErrorHandler' });
displayInfo('Error');
displayInfo(null);
// --------
const processData = (data: string | number | boolean | undefined): void => {
if (typeof data === 'string') {
console.log(`String value: ${data.toUpperCase()}`);
} else if (typeof data === 'number') {
console.log(`Number squared: ${data ** 2}`);
} else if (typeof data === 'boolean') {
console.log(`Boolean value: ${data ? 'True' : 'False'}`);
} else {
console.log('No valid data provided.');
}
};
let data;
processData('Hello'); //=> 'HELLO'
processData(4); //=> Number squared: 16
processData(true); //=> Boolean value: True
processData(data); // =>'No valid data provided.
}

View File

@@ -0,0 +1,69 @@
// Truthiness
/*
Truthiness wird verwendet, um zu bestimmen, ob eine Variable wahr oder falsch ist.
*/
// Falsy types in TypeScript/JavaScript are:
// - false
// - 0
// - -0
// - NaN
// - 0n (BigInt)
// - "" (empty string)
// - null
// - undefined
// - []
{
const showMessage = (userCount: number): string => {
// if (userCount) {
// return `There are ${userCount} users online.`;
// }
// return 'No users online.';
return userCount ? `There are ${userCount} users online.` : 'No users online.';
};
console.log(showMessage(5)); // => There are 5 users online.
// ----------
const printNames = (names: string[] | null): void => {
if (names) {
names.forEach((name) => {
console.log(name);
});
} else {
console.log('No names provided.');
}
};
printNames(['Adel', 'Ersin', 'Andreas', 'Kahleel']);
printNames(null);
// -------
const displayInput = (input: string | HTMLHeadingElement | null) => {
if (input) {
console.log(`Input provided: ${input}`);
} else {
console.log('No input provided.');
}
};
displayInput(document.querySelector('h2'));
// --------
const multiplyValues = (values: number[] | undefined, factor: number): number[] | undefined => {
if (!values) {
return undefined;
}
return values.map((value) => value * factor);
};
let numbers;
console.log(multiplyValues([1, 2, 3, 4], 2)); // => [2,4,6,8]
console.log(multiplyValues([], 2)); // => []
console.log(multiplyValues(numbers, 2)); // => undefined
}

View File

@@ -0,0 +1,51 @@
// Equality
/*
Equality wird verwendet, um zu bestimmen, ob zwei Werte gleich sind.
*/
{
const compareValues = (a: string | number, b: string | boolean): void => {
if (a === b) {
console.log(a.toUpperCase());
console.log(b.toLowerCase());
} else {
console.log(`a is ${a}, b is ${b}`);
}
};
// const result = compareValues('1', 1);
const result = compareValues(1, '1');
console.log(result);
// Loose equality
interface Container {
value: number | null | undefined;
}
// kein strikter Vergleich (BAD PRACTICE)
const scaleValue = (container: Container, factor: number): void => {
// Douglas Crockford considers the
// == (loose equality) operator to be "bad" because of its inconsistent and surprising behavior, particularly its lack of transitivity, which can lead to unexpected results in JavaScript. He advises against using == and its counterpart != in favor of the strict equality operators === and !== for clearer and safer code
if (container.value != null) {
container.value *= factor;
}
};
// ------
const processInput = (input: string | number | null): void => {
if (input !== null) {
if (typeof input === 'number') {
console.log(`Number input: ${input}`);
} else {
console.log(`String input: ${input}`);
}
} else {
console.log('No input provided.');
}
};
processInput(23); // => 'Number input: 23'
processInput('23'); // => 'String input: 23'
processInput(null); // => 'No input provided.'
}

View File

@@ -0,0 +1,53 @@
// In Operator
/*
Der In Operator wird verwendet, um zu bestimmen, ob ein Objekt ein bestimmtes Property hat.
*/
{
type Car = { drive: () => void };
type Boat = { sail: () => void };
const isCar = (vehicle: Car | Boat): vehicle is Car => {
return Object.hasOwn(vehicle, 'drive');
};
const operate = (vehicle: Car | Boat) => {
// vehicle.sail(); // Property 'sail' does not exist on type 'Car'.
// if (Object.hasOwn(vehicle, 'drive')) {
// if (isCar(vehicle)) {
if ('drive' in vehicle) {
vehicle.drive();
} else {
vehicle.sail();
}
};
const car: Car = { drive: () => console.log("I'm driving") };
const sealander: Boat = { sail: () => console.log("I'm sailing") };
operate(car);
operate(sealander);
// --------
type Dog = { bark: () => void };
type Bird = { fly: () => void };
type Robot = { walk?: () => void; fly?: () => void };
type Human = { walk: () => void };
const move = (entity: Dog | Bird | Robot) => {
if ('walk' in entity) {
entity.walk?.();
} else if ('fly' in entity) {
entity.fly?.();
}
};
const dog: Dog = { bark: () => console.log('Woof') };
const bird: Bird = { fly: () => console.log('Flying') };
const robot: Robot = { walk: () => console.log('Walking') };
move(dog);
move(bird);
move(robot);
}

View File

@@ -0,0 +1,50 @@
// Kontrollflussanalyse
/*
In TypeScript wird der Kontrollfluss analysiert, um zu bestimmen, welche Typen eine Variable haben kann. Dies wird auch als "Type Narrowing" bezeichnet.
Type Narrowing wird verwendet, um den Typ einer Variablen zu beschränken, wenn bestimmte Bedingungen erfüllt sind.
*/
{
const processData = (data: string | number | boolean): void => {
if (typeof data === 'boolean') {
console.log('Boolean value:', data);
} else if (typeof data === 'string') {
console.log('String value:', data.toUpperCase());
} else {
console.log('Number value:', data.toFixed(2));
}
};
processData(true);
processData('hello');
processData(123);
// Kontrollfluss mit Early Returns
const checkValue = (value: string | number): string => {
if (typeof value === 'string') {
return `String: ${value}`; // early return bei Narrowing
}
return `Number: ${value.toFixed(2)}`;
};
console.log(checkValue('hello'));
console.log(checkValue(123));
// ---
const describeInput = (input: string | number | null): string => {
if (input === null) {
return 'No input provided.';
}
if (typeof input === 'string') {
return `String input: ${input.toUpperCase()}`;
}
return `Number input: ${input.toFixed(2)}`;
};
console.log(describeInput('hello'));
console.log(describeInput(123));
console.log(describeInput(null));
}

View File

@@ -0,0 +1,44 @@
// Type Predicate
/*
Ein Type Predicate ist eine besondere Art von Funktion, die einen booleschen Wert zurückgibt, der angibt, ob eine Variable einem bestimmten Typ entspricht.
WICHTIG: "Außerdem grenzt es den Typ der Variablen auf der Grundlage des Ergebnisses der Prüfung ein."
*/
{
type Fish = { swim: () => void };
type Bird = { fly: () => void };
// "pet is Fish" <- Type predicate
const isFish = (pet: Fish | Bird): pet is Fish => {
// return 'swim' in pet; // in Operator führt Type- Narrowing durch.
return Object.hasOwn(pet, 'swim');
// return (pet as Fish).swim !== undefined;
};
const pet: Fish | Bird = { swim: () => console.log('Is swimming') };
if (isFish(pet)) {
pet.swim();
}
const handlePet = (pet: Fish | Bird) => {
if (isFish(pet)) {
pet.swim(); // TypeScript knows pet is Fish
} else {
pet.fly(); // TypeScript knows pet is Bird
}
};
handlePet(pet);
//------
const zoo: (Fish | Bird)[] = [
{ swim: () => console.log('Fish swimming') },
{ fly: () => console.log('Bird flying') },
];
const fishes = zoo.filter(isFish);
fishes.forEach((fish) => fish.swim());
}