// 1. Primitivní typy - lze zjednodušit
// S generics:
function processValue<T extends string>(value: T) { }
// Jednodušeji:
function processValue(value: string) { }

// 2. Union typy - lze zjednodušit
type Fruit = "apple" | "banana" | "orange";
// S generics:
function processFruit<T extends Fruit>(fruit: T) { }
// Jednodušeji:
function processFruit(fruit: Fruit) { }

// 3. Literal typy - lze zjednodušit
// S generics:
function processLiteral<T extends "yes" | "no">(answer: T) { }
// Jednodušeji:
function processLiteral(answer: "yes" | "no") { }

// 4. Array typy - lze zjednodušit v základním případě
// S generics:
function processArray<T extends any[]>(arr: T) { }
function processStringArray<T extends string[]>(arr: T) { }
// Jednodušeji:
function processArray(arr: any[]) { }
function processStringArray(arr: string[]) { }

// 5. Function typy - lze zjednodušit
type Logger = (msg: string) => void;
// S generics:
function withLogging<T extends Logger>(logger: T) { }
// Jednodušeji:
function withLogging(logger: Logger) { }

// 6. Class typy - lze zjednodušit v základním případě
class Animal { }
// S generics:
function processClass<T extends Animal>(instance: T) { }
// Jednodušeji:
function processClass(instance: Animal) { }

// 7. Generický typ s extends - POUZE PŘES GENERIC CONSTRAINT
interface Box<T> {
    value: T;
}
interface NumberBox<T extends number> extends Box<T> {
    increment(): void;
}

// 8. Kombinace více typů - lze zjednodušit
type StringWithLength = string & { length: number };
// S generics:
function processString<T extends string & { length: number }>(value: T) { }
// Jednodušeji:
function processString(value: StringWithLength) { }

// 9. Conditional type - POUZE PŘES GENERIC CONSTRAINT
type NonNullable<T> = T extends null | undefined ? never : T;