Read nested values with a type-safe path

TypeScript
// Dotted paths are checked at compile time and resolve to the value type.
type Primitive = string | number | boolean | null | undefined;

type Paths<T> = T extends Primitive ? never : {
  [K in keyof T & string]: T[K] extends Primitive ? K : K | `${K}.${Paths<T[K]>}`;
}[keyof T & string];

type PathValue<T, P extends string> = P extends `${infer Head}.${infer Tail}`
  ? Head extends keyof T ? PathValue<T[Head], Tail> : never
  : P extends keyof T ? T[P] : never;

function getPath<T, P extends Paths<T> & string>(source: T, path: P): PathValue<T, P> {
  let current: unknown = source;
  for (const key of path.split('.')) {
    if (current === null || typeof current !== 'object') {
      throw new TypeError(`cannot read "${path}"`);
    }
    current = (current as Record<string, unknown>)[key];
  }
  return current as PathValue<T, P>;
}

const user = { name: 'Ada', address: { city: 'London', zip: 'N1' } };
console.log(getPath(user, 'address.city').toUpperCase()); // LONDON