diff --git a/05_typescript/faq/falsy-values.js b/05_typescript/faq/falsy-values.js
new file mode 100644
index 0000000..5ae9fbf
--- /dev/null
+++ b/05_typescript/faq/falsy-values.js
@@ -0,0 +1,6 @@
+const test = [];
+if (test) {
+ console.log('truthy');
+} else {
+ console.log('falsy');
+}
diff --git a/05_typescript/faq/falsy-values.ts b/05_typescript/faq/falsy-values.ts
new file mode 100644
index 0000000..5ae9fbf
--- /dev/null
+++ b/05_typescript/faq/falsy-values.ts
@@ -0,0 +1,6 @@
+const test = [];
+if (test) {
+ console.log('truthy');
+} else {
+ console.log('falsy');
+}
diff --git a/05_typescript/unterricht/tag31/01_ts-narrowing-guards/assets/img/what-is-ts.webp b/05_typescript/unterricht/tag31/01_ts-narrowing-guards/assets/img/what-is-ts.webp
new file mode 100644
index 0000000..d329dbb
Binary files /dev/null and b/05_typescript/unterricht/tag31/01_ts-narrowing-guards/assets/img/what-is-ts.webp differ
diff --git a/05_typescript/unterricht/tag31/01_ts-narrowing-guards/assets/js/01_narrowing.js b/05_typescript/unterricht/tag31/01_ts-narrowing-guards/assets/js/01_narrowing.js
new file mode 100644
index 0000000..6701eb3
--- /dev/null
+++ b/05_typescript/unterricht/tag31/01_ts-narrowing-guards/assets/js/01_narrowing.js
@@ -0,0 +1,55 @@
+(() => {
+ // 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}`;
+ }
+ };
+ console.log(processPadding(2, "px"));
+ console.log(processPadding("1.5", "rem"));
+ console.log(processPadding(10, "%"));
+ console.log(processPadding("10", "%"));
+ 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}.`;
+ }
+ return `The string is "${input.toUpperCase()}".`;
+ };
+ handleInput(true);
+ handleInput(10);
+ handleInput("super");
+ const processNumbers = (numbers) => {
+ numbers?.forEach((num) => console.log(num * 2));
+ if (Array.isArray(numbers)) {
+ numbers.forEach((num) => console.log(num * 2));
+ }
+ };
+ processNumbers([1, 2, 3, 4]);
+ processNumbers(null);
+ const displayInfo = (input) => {
+ if (input !== null && typeof input === "object") {
+ console.log(input.name);
+ } else {
+ console.log(input);
+ }
+ };
+ displayInfo("Error");
+ displayInfo({ name: "ErrorHandler" });
+ displayInfo(null);
+ console.log("###");
+ }
+})();
diff --git a/05_typescript/unterricht/tag31/01_ts-narrowing-guards/assets/js/02_truthiness.js b/05_typescript/unterricht/tag31/01_ts-narrowing-guards/assets/js/02_truthiness.js
new file mode 100644
index 0000000..6ba7521
--- /dev/null
+++ b/05_typescript/unterricht/tag31/01_ts-narrowing-guards/assets/js/02_truthiness.js
@@ -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(["Christian", "Florian", "Stefan", "Benjamin"]);
+ printNames([]);
+ printNames(null);
+ const displayInput = (input) => {
+ if (input) {
+ console.log(`Input provided: ${input}`);
+ } else {
+ console.log("No input provided.");
+ }
+ };
+ displayInput(document.querySelector("h2"));
+ displayInput("Hello World");
+ displayInput(null);
+ const multiplyValues = (values, factor) => {
+ return values ? values.map((value) => value * factor) : void 0;
+ };
+ let numbers;
+ console.log(multiplyValues([1, 2, 3, 4], 2));
+ console.log(multiplyValues([], 2));
+ console.log(multiplyValues([], 2));
+ console.log(multiplyValues(numbers, 2));
+ console.log("###");
+ }
+})();
diff --git a/05_typescript/unterricht/tag31/01_ts-narrowing-guards/assets/js/03_equality.js b/05_typescript/unterricht/tag31/01_ts-narrowing-guards/assets/js/03_equality.js
new file mode 100644
index 0000000..0f31833
--- /dev/null
+++ b/05_typescript/unterricht/tag31/01_ts-narrowing-guards/assets/js/03_equality.js
@@ -0,0 +1,37 @@
+(() => {
+ // 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;
+ }
+ };
+ scaleValue({ value: 123 }, 2);
+ scaleValue({ value: null }, 1);
+ const processInput = (input) => {
+ if (input !== null) {
+ if (typeof input === "number") {
+ console.log(`Number input: ${input.toFixed(2)}`);
+ } else {
+ console.log(`String input: ${input.toUpperCase()}`);
+ }
+ } else {
+ console.log("No input provided.");
+ }
+ };
+ processInput(23);
+ processInput("23");
+ processInput(null);
+ console.log("###");
+ }
+})();
diff --git a/05_typescript/unterricht/tag31/01_ts-narrowing-guards/assets/js/04_in-operator.js b/05_typescript/unterricht/tag31/01_ts-narrowing-guards/assets/js/04_in-operator.js
new file mode 100644
index 0000000..1cd87df
--- /dev/null
+++ b/05_typescript/unterricht/tag31/01_ts-narrowing-guards/assets/js/04_in-operator.js
@@ -0,0 +1,5 @@
+(() => {
+ // src/04_in-operator.ts
+ {
+ }
+})();
diff --git a/05_typescript/unterricht/tag31/01_ts-narrowing-guards/index.html b/05_typescript/unterricht/tag31/01_ts-narrowing-guards/index.html
new file mode 100644
index 0000000..e99f67d
--- /dev/null
+++ b/05_typescript/unterricht/tag31/01_ts-narrowing-guards/index.html
@@ -0,0 +1,26 @@
+
+
+
+
+
+ TypeScript - Grundlagen
+
+
+
+
+
+
+
+
+
+
TypeScript - Grundlagen
+
+ TypeScript ist eine von Microsoft entwickelte Skriptsprache, die auf den Vorschlägen zum ECMAScript-6-Standard
+ basiert und statische Typisierung zu JavaScript hinzufügt. Sprachkonstrukte von TypeScript, wie Klassen,
+ Vererbung, Module und anonyme Funktionen, wurden auch in ECMAScript 6 übernommen.
+
+
+
+
+
+
diff --git a/05_typescript/unterricht/tag31/01_ts-narrowing-guards/package-lock.json b/05_typescript/unterricht/tag31/01_ts-narrowing-guards/package-lock.json
new file mode 100644
index 0000000..93e05a3
--- /dev/null
+++ b/05_typescript/unterricht/tag31/01_ts-narrowing-guards/package-lock.json
@@ -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.2"
+ }
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz",
+ "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz",
+ "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz",
+ "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz",
+ "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz",
+ "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz",
+ "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz",
+ "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz",
+ "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz",
+ "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz",
+ "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz",
+ "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz",
+ "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz",
+ "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz",
+ "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz",
+ "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz",
+ "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz",
+ "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz",
+ "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz",
+ "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz",
+ "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz",
+ "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openharmony-arm64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz",
+ "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz",
+ "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz",
+ "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz",
+ "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz",
+ "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.28.2",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz",
+ "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.28.2",
+ "@esbuild/android-arm": "0.28.2",
+ "@esbuild/android-arm64": "0.28.2",
+ "@esbuild/android-x64": "0.28.2",
+ "@esbuild/darwin-arm64": "0.28.2",
+ "@esbuild/darwin-x64": "0.28.2",
+ "@esbuild/freebsd-arm64": "0.28.2",
+ "@esbuild/freebsd-x64": "0.28.2",
+ "@esbuild/linux-arm": "0.28.2",
+ "@esbuild/linux-arm64": "0.28.2",
+ "@esbuild/linux-ia32": "0.28.2",
+ "@esbuild/linux-loong64": "0.28.2",
+ "@esbuild/linux-mips64el": "0.28.2",
+ "@esbuild/linux-ppc64": "0.28.2",
+ "@esbuild/linux-riscv64": "0.28.2",
+ "@esbuild/linux-s390x": "0.28.2",
+ "@esbuild/linux-x64": "0.28.2",
+ "@esbuild/netbsd-arm64": "0.28.2",
+ "@esbuild/netbsd-x64": "0.28.2",
+ "@esbuild/openbsd-arm64": "0.28.2",
+ "@esbuild/openbsd-x64": "0.28.2",
+ "@esbuild/openharmony-arm64": "0.28.2",
+ "@esbuild/sunos-x64": "0.28.2",
+ "@esbuild/win32-arm64": "0.28.2",
+ "@esbuild/win32-ia32": "0.28.2",
+ "@esbuild/win32-x64": "0.28.2"
+ }
+ }
+ }
+}
diff --git a/05_typescript/unterricht/tag31/01_ts-narrowing-guards/package.json b/05_typescript/unterricht/tag31/01_ts-narrowing-guards/package.json
new file mode 100644
index 0000000..e116d3a
--- /dev/null
+++ b/05_typescript/unterricht/tag31/01_ts-narrowing-guards/package.json
@@ -0,0 +1,14 @@
+{
+ "name": "01_ts-narrowing-guards",
+ "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.2"
+ }
+}
diff --git a/05_typescript/unterricht/tag31/01_ts-narrowing-guards/src/01_narrowing.ts b/05_typescript/unterricht/tag31/01_ts-narrowing-guards/src/01_narrowing.ts
new file mode 100644
index 0000000..374cd6a
--- /dev/null
+++ b/05_typescript/unterricht/tag31/01_ts-narrowing-guards/src/01_narrowing.ts
@@ -0,0 +1,99 @@
+// 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 => {
+ // Property 'toUpperCase' does not exist on type 'number'.
+ // console.log(value.toUpperCase())
+
+ if (typeof value === 'string') {
+ console.log(value.toUpperCase());
+ // Type Guard: typeof value === "string"
+ // Narrowing: 'value' is now of type 'string'
+ } 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: string | number, input: string): string => {
+ // The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.
+ // return `${padding * 2}${input}`;
+
+ // Property 'toFixed' does not exist on type 'string | number'.
+ //Property 'toFixed' does not exist on type 'string'.
+ // return `${padding.toFixed(2)}${input}`;
+
+ // Narrowing
+ 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}`;
+ }
+ };
+
+ console.log(processPadding(2, 'px'));
+ console.log(processPadding('1.5', 'rem'));
+ console.log(processPadding(10, '%'));
+ console.log(processPadding('10', '%'));
+
+ // --------
+
+ const handleInput = (input: boolean | number | string): string => {
+ 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}.`;
+ }
+
+ 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) => {
+ // 'numbers' is possibly 'null'.
+ // numbers.forEach((num) => console.log(num * 2));
+
+ numbers?.forEach((num) => console.log(num * 2));
+
+ // 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({});
+ processNumbers(null);
+
+ // ----------
+
+ const displayInfo = (input: string | { name: string } | null): void => {
+ // Property 'name' does not exist on type 'string | { name: string; }'.
+ //Property 'name' does not exist on type 'string'.
+ // console.log(input.name);
+
+ if (input !== null && typeof input === 'object') {
+ console.log(input.name);
+ } else {
+ console.log(input);
+ }
+ };
+
+ displayInfo('Error');
+ displayInfo({ name: 'ErrorHandler' });
+ displayInfo(null);
+ // displayInfo(123);
+
+ console.log('###');
+}
diff --git a/05_typescript/unterricht/tag31/01_ts-narrowing-guards/src/02_truthiness.ts b/05_typescript/unterricht/tag31/01_ts-narrowing-guards/src/02_truthiness.ts
new file mode 100644
index 0000000..1488292
--- /dev/null
+++ b/05_typescript/unterricht/tag31/01_ts-narrowing-guards/src/02_truthiness.ts
@@ -0,0 +1,73 @@
+// 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(['Christian', 'Florian', 'Stefan', 'Benjamin']);
+ printNames([]);
+ printNames(null); // => 'No names provided.'
+ // printNames(); // Expected 1 arguments, but got 0.
+
+ // -------
+
+ const displayInput = (input: string | HTMLHeadingElement | null) => {
+ if (input) {
+ console.log(`Input provided: ${input}`);
+ } else {
+ console.log('No input provided.');
+ }
+ };
+
+ displayInput(document.querySelector('h2'));
+ displayInput('Hello World');
+ displayInput(null);
+
+ // --------
+
+ const multiplyValues = (values: number[] | undefined, factor: number): number[] | undefined => {
+ // if (!values) {
+ // return undefined;
+ // }
+ // return values.map((value) => value * factor);
+
+ return values ? values.map((value) => value * factor) : undefined;
+ };
+
+ let numbers;
+
+ console.log(multiplyValues([1, 2, 3, 4], 2)); // => [2,4,6,8]
+ console.log(multiplyValues([], 2)); // => []
+ console.log(multiplyValues([], 2)); // => []
+ console.log(multiplyValues(numbers, 2)); // => undefined
+
+ console.log('###');
+}
diff --git a/05_typescript/unterricht/tag31/01_ts-narrowing-guards/src/03_equality.ts b/05_typescript/unterricht/tag31/01_ts-narrowing-guards/src/03_equality.ts
new file mode 100644
index 0000000..fb180b6
--- /dev/null
+++ b/05_typescript/unterricht/tag31/01_ts-narrowing-guards/src/03_equality.ts
@@ -0,0 +1,58 @@
+// Equality - wird verwendet, um zu bestimmen, ob zwei Werte gleich sind.
+{
+ const compareValues = (a: string | number, b: string | boolean): void => {
+ // Property 'toUpperCase' does not exist on type 'string | number'.
+ // Property 'toUpperCase' does not exist on type 'number'.
+ // console.log(a.toUpperCase());
+
+ // equality narrowing
+ 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;
+ }
+ };
+
+ scaleValue({ value: 123 }, 2);
+ scaleValue({ value: null }, 1);
+
+ // ------
+ const processInput = (input: string | number | null): void => {
+ if (input !== null) {
+ if (typeof input === 'number') {
+ console.log(`Number input: ${input.toFixed(2)}`);
+ } else {
+ console.log(`String input: ${input.toUpperCase()}`);
+ }
+ } else {
+ console.log('No input provided.');
+ }
+ };
+
+ processInput(23); // => 'Number input: 23.00'
+ processInput('23'); // => 'String input: 23'
+ processInput(null); // => 'No input provided.'
+
+ console.log('###');
+}
diff --git a/05_typescript/unterricht/tag31/01_ts-narrowing-guards/src/04_in-operator.ts b/05_typescript/unterricht/tag31/01_ts-narrowing-guards/src/04_in-operator.ts
new file mode 100644
index 0000000..92a7231
--- /dev/null
+++ b/05_typescript/unterricht/tag31/01_ts-narrowing-guards/src/04_in-operator.ts
@@ -0,0 +1,5 @@
+// In Operator - wird verwendet, um zu bestimmen, ob ein Objekt ein bestimmtes Property hat.
+{
+ type Car = { drive: () => void };
+ type Boat = { sail: () => void };
+}