typescript - Stvorite uniju od vrijednosti ugniježđenog objekta s različitim ključevima
S obzirom da imam sljedeći Options tip
interface Options {
parent1: {
child1: {
foo: 'bar'
}
};
parent2: {
child2: {
baz: 'daz'
}
};
}
Kako to mogu pretvoriti u uniju svih vrijednosti svojstava drugog nivoa, u ovom slučaju
{ foo: 'bar' } | { baz: 'daz' }
Pokušao sam sljedeće
type KnownOptions = Options[keyof Options][keyof Options[keyof Options]];
Ali to funkcionira samo ako su svojstva na drugoj razini djece ista kod svih svojstava na vrhunskoj razini. Npr. funkcionira kada preimenujem child2 u `child1
Igralište
Odgovor #1
Možete koristiti mapirani tip za dohvaćanje ugniježđenog tipa:
type KnownOptions<T> = T extends {
[k in keyof T]: {
[k: string]: infer OptionValue
}
} ? OptionValue : never
// Good:
const a: KnownOptions<Options> = { foo: 'bar' }
const b: KnownOptions<Options> = { baz: 'daz' }
// Expect errors:
const c: KnownOptions<Options> = { foo: 'bad value' }
const d: KnownOptions<Options> = { badKey: 'bar' }
Igralište
Ovo je generički tip koji prihvaća tip koji ima dvije razine ključeva. Uvjetni tip (označen ternarnim T extends Type ? A : B) kaže „ako je generički tip T objekt barem 2 razine duboko, onda vrati tip za svaku od tih drugih razina. Inače, vrati never tip, jer je generički tip nevažeći.
infer OptionalValue govori „koji god tip je ovdje, spremi ga kao OptionValue“. To se zatim vraća kroz uvjetni tip, nakon što su mu spremljeni višestruki tipovi, stvarajući uniju svakog tipa.
Moram priznati, nisam potpuno siguran zašto prva razina ključa mora biti k in keyof T, ali druga razina može biti samo k: string. Ali, to je bio jedini način da to uspješno radi.
Odgovor #2
Pisao bih KnownOptions ovako:
type KnownOptions = { [K in keyof Options]: Options[K][keyof Options[K]] }[keyof Options];
Ovdje mapiramo svaku svojstvo Options u uniju njenih svojstava, a zatim spajamo sve te unije zajedno. Možda će imati više smisla ako to napišemo u terminima ValueOf<T> definirano ovako:
type ValueOf<T> = T[keyof T];
type KO = ValueOf<{ [K in keyof Options]: ValueOf<Options[K]> }>;
Dakle, ValueOf<T> vam daje uniju tipova vrijednosti svojstava objekta T (npr., ValueOf<{a: string, b: number}> je string | number), i tako ono što radite je mapiranje svakog svojstva Options pomoću ValueOf, a zatim uzimate ValueOf za cijelu stvar.
Možete provjeriti da svaka od tih definicija evaluira na {foo: "bar";} | {baz: "daz";} kako je željeno.
U redu, nadam se da pomaže; sretno!
Poveznica na Playground za kod
