// 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