diff --git a/src/05-forgeschrittenes-typsystem/guards.ts b/src/05-forgeschrittenes-typsystem/guards.ts new file mode 100644 index 0000000..0fa44c8 --- /dev/null +++ b/src/05-forgeschrittenes-typsystem/guards.ts @@ -0,0 +1,8 @@ +function isString(value: unknown): value is string { + return typeof value === 'string'; +} + +const data: unknown = 'Test'; +if (isString(data)) { + console.log(data.toUpperCase()); +} diff --git a/src/05-forgeschrittenes-typsystem/mapped-types.ts b/src/05-forgeschrittenes-typsystem/mapped-types.ts index e69de29..e90142b 100644 --- a/src/05-forgeschrittenes-typsystem/mapped-types.ts +++ b/src/05-forgeschrittenes-typsystem/mapped-types.ts @@ -0,0 +1,164 @@ +type Person = { + name: string; + age: number; +}; + +const person: Person = { + name: 'Alice', + age: 28, +}; + +type Optional = { + [K in keyof T]?: T[K]; +}; + +type PartialPerson = Optional; + +const p: PartialPerson = { + name: 'Bob', +}; + +type Readonly = { readonly [K in keyof T]: T[K] }; +type ReadonlyPerson = Readonly; + +const p2: ReadonlyPerson = { + name: 'Hans', + age: 32, +}; + +type User = { + name: string; + settings: { + darkMode: boolean; + }; +}; + +type ReadonlyUser = Readonly; + +const user: ReadonlyUser = { + name: 'Fritz', + settings: { + darkMode: true, + }, +}; + +user.settings.darkMode = false; + +type DeepReadonly = { + readonly [K in keyof T]: T[K] extends object ? DeepReadonly : T[K]; +}; +type DeepReadonlyUser = DeepReadonly; +const user2: DeepReadonlyUser = { + name: 'Tim', + settings: { + darkMode: false, + }, +}; + +// user2.settings.darkMode = true; + +type Nullable = { + [K in keyof T]: T[K] | null; +}; +type NullableUser = Nullable; +type Required = { + [K in keyof T]-?: T[K]; +}; + +type RequiredPerson = Required; +type Mutable = { + -readonly [K in keyof T]: T[K]; +}; + +type MutablePerson = Mutable; + +type x = Partial<{ user: string }>; + +// Conditional Types +// T extends U ? X : Y + +type IsString = T extends string + ? 'Ja, ist ein String' + : 'Nein, kein String'; + +type Test1 = IsString; +type Test2 = IsString; + +function checkType(value: T): IsString { + return ( + typeof value === 'string' ? 'Ja, ist ein String' : 'Nein, kein String' + ) as IsString; +} + +console.log(checkType('Hello')); +console.log(checkType(42)); + +type IsStringOrBoolean = T extends string ? true : false; + +function isString(value: T): IsStringOrBoolean { + return (typeof value === 'string') as IsStringOrBoolean; +} + +console.log(isString('Test')); +console.log(isString(true)); + +function isString2(value: unknown): value is string { + return typeof value === 'string'; +} + +let x: unknown; +x = 'test'; +x = 42; + +if (isString2(x)) { + console.log('hey is string', x.length); +} + +console.log(isString2({ obj: true })); +console.log(isString2('test')); + +// type NonNullable = T extends null | undefined ? never : T; +type A = NonNullable; + +type NullableTest = { + test: string | null; + deep: { + test2: number | null; + }; +}; + +type B = { + [K in keyof T]: T[K] extends object ? B : NonNullable; +}; + +type NonNullableTest = B; +const nnt: NonNullableTest = { + test: 'string', + deep: { + test2: 42, + }, +}; + +type UnwrapPromise = T extends Promise ? U : T; + +type A2 = UnwrapPromise>; +type B2 = UnwrapPromise>; +type C2 = UnwrapPromise; + +type FirstElement = T extends [any, ...any[]] ? T[0] : never; + +type A3 = FirstElement<[1, 2, 3]>; +type B3 = FirstElement<['a', 2, true]>; +type C3 = FirstElement<[]>; + +type xxx = Partial; + +type Person2 = { + name: string; + age: number; + address: string; +}; + +type PersonName = Pick; + +type PersonWithoutAddress = Omit; diff --git a/src/05-forgeschrittenes-typsystem/type-queries.ts b/src/05-forgeschrittenes-typsystem/type-queries.ts new file mode 100644 index 0000000..269516d --- /dev/null +++ b/src/05-forgeschrittenes-typsystem/type-queries.ts @@ -0,0 +1,63 @@ +const value = 'Hallo'; +console.log(typeof value); + +function printLength(value: string | number) { + if (typeof value === 'string') { + console.log(value.length); + } else { + console.log(value.toFixed(2)); + } +} + +printLength('TypeScript'); +printLength(42); + +class Animal {} +class Dog extends Animal {} + +const dog = new Dog(); + +console.log(dog instanceof Dog); +console.log(dog instanceof Animal); +console.log(dog instanceof Object); + +class Car { + drive() { + console.log('Fahren...'); + } +} + +class Boat { + sail() { + console.log('Segeln...'); + } +} + +type Vehicle = Car | Boat; + +function move(vehicle: Vehicle) { + if (vehicle instanceof Car) { + vehicle.drive(); + } else { + vehicle.sail(); + } +} + +move(new Car()); +move(new Boat()); + +const obj = { + name: 'John', +}; +console.log(typeof obj === 'object'); + +if (!(obj instanceof Car)) { + console.log('obj is a car'); +} + +if ('name' in obj) { + console.log(obj.name); +} + +// console.log('text' instanceof String); +console.log(typeof 'text' === 'string');