typescript - Betinget type ikke innsnevret i falsk gren


La oss si at jeg trenger en type som gir meg verdien av en bestemt egenskap til Obj. Det eneste problemet er at det, som ofte i livet, finnes spesialtilfeller. Så jeg har følgende kode:

interface Obj {
  foo: number;
}

// Ignore the actual type of special case, it's only for
// demonstrative purposes.
type SpecialCase = { id: number };
type ObjKey = keyof Obj | "specialCase";

// This is the desired type I need:
type ObjVal<Key extends ObjKey> = Key extends "foo" ? Obj[Key] : SpecialCase;

Det fungerer ganske bra. Kompilatoren bruker Key extends "foo" for å fortelle at "foo" er en faktisk egenskap av Obj, og lar meg indeksere den. Men dessverre har Obj ganske mange flere nøkler enn bare "foo". Så den åpenbare neste handlingen er å snu betingelsen. Men av en eller annen grunn klarer ikke TypeScript å begrense den falske grenen av uttrykket:

interface Obj {
  foo1: number;
  foo2?: number;
  bar1: string;
  bar2?: string;
}

type SpecialCase = { id: number };
type ObjKey = keyof Obj | "specialCase";

type ObjVal<Key extends ObjKey> = Key extends "specialCase" ? SpecialCase : Obj[Key];
// Error: Type 'Key' cannot be used to index type 'Obj'.(2536)

Lekeplass

Jeg har (raskt) lest kapitlet om betingede typer, men har ikke funnet noen nyttig informasjon.

Denne oppførselen virker merkelig for meg. Den eneste grunnen jeg kan tenke meg til at TypeScript gjør dette, er hvis Key er "mer" enn bare ObjKey. Men så vidt jeg vet, tillater begrensningen på generikken, Key extends ObjKey, bare varianter av ObjKey.

Jeg har søkt litt på nettet etter dette, men jeg ser ut til å mangle de riktige søkeordene, og kunne ikke finne det. Tips blir svært verdsatt!

Svar #1

I tilfelle noen finner dette i fremtiden: Dette er faktisk en manglende funksjon og, så vidt jeg vet, ikke planlagt av TypeScript-teamet.

Jeg har spurt om følgende GitHub-issue: #51040, som ble merket som en duplikat av #48710. Den saken har for øyeblikket ikke fått mye oppmerksomhet, så jeg tror ikke dette vil gå videre med det første. Men den er merket som "venter på mer tilbakemelding", så hvis du har noe, vet du nå hvor du skal legge det :).

Relaterte artikler