For any type T, keyof T is the union of known, public property names of T.

interface Person {
  age: number
  name: string
}
 
type PersonKeys = keyof Person // "age" | "name"

extends is used to constrain the type of a generic parameter.

<T, K extends keyof T> restrict K to be the public property name of T.

It is nothing to do with extending a type or inheritance, contrary to extending interfaces.

function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key]
}
 
const person: Person {
  age: 22,
  name: "mancuoj",
}
 
const name = getProperty(person, "name");
 
// ❌ gender is not a property of person
const gender = getProperty(person, "gender");

in is used to define index signature that we want to type with a union of string, number or symbol literals.

In combination with keyof, we can use it to create a so called mapped type, which re-maps all properties of origin type.

type MyPick<T, K extends keyof T> = {
  [Key in K]: T[Key]
}

Thanks