typescript - Varför kan inte detta villkor med generisk keyof lösas direkt?
function broken<T>(value: T) {
type Test = keyof T extends keyof T ? 1 : 0
}
Varför kan inte Test i exemplet ovan lösas direkt till 1? Det är något jag inte förstår om kompilatorn som borde svara på den här frågan åt mig.
Intressant nog finns det en lösning:
function workaround<T>(value: T) {
type Test = [keyof T] extends [keyof T] ? 1 : 0
}
Lekplats här
Svar #1
Svaret på frågan involverar förmodligen en buggfix som introducerades i TypeScript 3.3. Beskrivningen av det nya sättet att utvärdera villkorliga typer är:
För en konditionell typ
T extends U ? X : Y, är algoritmen vi använder för att avgöra om vi ska skjuta upp upplösningen av en konditionell typ:
- vi löser oss till
YnärTinte är tilldelbar tillUmed beaktande av alla typparametrar som refereras iTochUrelaterade (dvs.Tär definitivt inte tilldelbar tillU),- annars löser vi till
XnärTkan tilldelasUmed hänsyn till alla typparametrar som refereras iTochUsom orelaterade (dvs.Tkan definitivt tilldelasU),- annars skjuter vi upp lösningen.
Så det ser ut som att keyof T extends keyof T ? 1 : 0 är uppskjuten, eftersom keyof T1 inte kan tilldelas keyof T2 när T1 och T2 är orelaterade typer. Denna uppskjutning är inte exakt fel, men det verkar som en begränsning.
Faktiskt, om jag testar din kod i TS 3.2.1 löses den snabbt, så detta var en förändring som infördes för TS3.3.
Nyfiket nog ser min läsning av den buggfixens algoritmbeskrivning ut som att den borde gälla för din lösning också. Jag är inte säker på varför [keyof T] extends [keyof T] skulle ändra saker, eftersom [keyof T1] inte är definitivt tilldelningsbara till [keyof T2], om T1 och T2 inte är relaterade. Så några mysterier återstår fortfarande här. Har inte kunnat lista ut det än, så jag kommer nog bara att ge upp nu. Tja, så är det!
Det ser också ut som om någon rapporterade exakt detta problem där X extends X ? 1 : 0 inte löses snabbt (och de märkte också att inneslutning i en en-tuple "fixar" det), och problemet markerades som ett fel, så kanske det kommer att tas upp?
Okej, hoppas det hjälper; lycka till!