Skip to content

Instantly share code, notes, and snippets.

@vimanvh

vimanvh/path.ts

Last active Feb 20, 2021
Embed
What would you like to do?
// Typ složeného objektu pro testování
interface Person {
firstName: string,
lastName: string,
child: {
firstName: string,
lastName: string,
age: number,
toy: {
name: string
}
}
}
// Instance objektu pro testování
const person: Person = {
firstName: "Petr",
lastName: "Novák",
child: {
firstName: "Anna",
lastName: "Nováková",
age: 5,
toy: {
name: "pandulak"
}
}
}
/**
* Typovaná cesta v objektu typu T
*/
type Path<T,
K1 extends keyof T,
K2 extends keyof T[K1] = never,
K3 extends keyof T[K1][K2] = never>
= [K1] | [K1, K2] | [K1, K2, K3];
/**
* Vrací hodnotu typované cesty "path" v objektu "o"
*/
function getProp<
T,
K1 extends keyof T,
K2 extends keyof T[K1] = never,
K3 extends keyof T[K1][K2] = never>
(o: T, path: Path<T, K1, K2, K3>) {
switch (path.length) {
case 1: return o[path[0]];
case 2: return o[path[0]] !== undefined ? o[path[0]][path[1]] : undefined;
case 3: return o[path[0]] !== undefined && o[path[0]][path[1]] !== undefined ? o[path[0]][path[1]][path[2]] : undefined;
}
}
// Toto je ok a krásně funguje, zafunguje správně typová inference
const toyName = getProp(person, ["child", "toy", "name"]);
console.log(toyName);
// Potřebuji ale umět napsat typovou definici cesty nezávisle na instanci takto
const path1: Path<Person> = ["child", "toy", "name"] // chyba kompilace
// Jde to jedině takto, což je naprosto prakticky nepoužitelné, protože
// potřebuji typ cesty odvodit pouze z typu objektu, tedy žádná parametrizace pomocí klíčů
const path2: Path<Person, "child", "toy", "name"> = ["child", "toy", "name"]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment