The code explain herself, but it's basically you type a interface without say if it should be a string or number, but after used it should follow the first called type

// The video for this file:
// <https://youtu.be/oGczYPNAs1k>

export interface Cat {
  age: number;
  name: string;
  eat(): void;
}

type ReadonlyCat = {
  readonly [P in keyof Cat]: Cat[P];
}
type GenericReadonly<T> = {
  readonly [P in keyof T]: T[P];
}
type ReadonlyCat2 = GenericReadonly<Cat>;

// Transformo em não obrigatório os campos
type GenericPartial<T> = {
  [P in keyof T]?: T[P];
}
type PartialCat = GenericPartial<Cat>;
type ReadonlyPartialCat = GenericReadonly<PartialCat>;

type GenericNullable<T> = {
  [P in keyof T]: T[P] | null;
}
type NullableCat = GenericNullable<Cat>;

interface Proxy<T> {
  get(): T;
  set(value: T): void;
}

// Reutilizo uma interface, agora cada T irá ter um get set
type Proxied<T> = {
  [P in keyof T]: Proxy<T[P]>;
}
type ProxiedCat = Proxied<Cat>;
const cat: ProxiedCat = null;
cat.age.get();

type A = Readonly<Cat>;
type B = Partial<Cat>;
type C = Pick<Cat, 'age' | 'eat'>;

The video I used as reference:

https://youtu.be/oGczYPNAs1k