function getFirstElement(arr: any[]): any {
  return arr[0];
}

const first = getFirstElement(['Hello', 'World']);
console.log(first.toUpperCase());

function getFirstElementGeneric<T>(arr: T[]): T {
  return arr[0];
}
const array = ['Hello', '1', 'World'];
const firstGen = getFirstElementGeneric<string>(array);
console.log(firstGen.length);

class UserRepository {
  private users: string[] = [];

  add(user: string) {
    this.users.push(user);
  }

  getAll(): string[] {
    return this.users;
  }
}

class Repository<T> {
  private items: T[] = [];

  add(item: T) {
    this.items.push(item);
  }

  getAll(): T[] {
    return this.items;
  }
}

const userRepo = new Repository<{ name: string; age: number }>();
userRepo.add({ name: 'Alice', age: 28 });
userRepo.add({ name: 'Bob', age: 42 });

console.log(userRepo.getAll());

async function fetchData<T>(url: string): Promise<T> {
  const response = await fetch(url);
  return response.json();
}

type User = {
  id: number;
  name: string;
};

export async function getUsers() {
  const user = await fetchData<User>(
    'https://jsonplaceholder.typicode.com/posts/1'
    // 'https://jsonplaceholder.typicode.com/users/1'
    // 'https://jsonplaceholder.typicode.com/users/1'
  );
  console.log(user.name);
}

// getUsers();

function logLength<TKey extends { length: number }, TValue>(
  item: TKey,
  num?: TValue
): void {
  console.log(item.length);
}

logLength<string, number>('Hallo', 42);
logLength(['a', 'b']);
logLength(42);

const obj = {
  name: 'Alice',
  age: 22,
};

console.log(Object.keys(obj));
console.log(Object.getOwnPropertyNames(obj));

function identity<T>(value: T): T {
  return value;
}

function identity(value) {
  return value;
}
