Hva er betydningen av `...` i et typeuttrykk som TypeScript slutter seg til?
Jeg har en funksjon say som fungerer slik:
say()==>""say("hello")()==>"hello"say("hello")("how")("are")("you")()==>"hei hvordan har du det"
og implementeres i TypeScript på følgende måte:
function say(first?: string) {
if (first === undefined) {
return ""
}
return (second?: string) => {
if (second === undefined) {
return first
}
return say(`${first} ${second}`)
}
}
Jeg utelot returtypen for å se hva TypeScript ville utlede, og det ga meg dette uttrykket:
function say(first?: string): "" | ((second?: string) => string | ...)
... ser ut til å referere til det faktum at ethvert forsøk på å utlede en type er sirkulært, siden
sayreturnerer enten den tomme strengen eller en funksjon som returnerer enten en streng eller en funksjon som returnerer enten en streng eller en funksjon som returnerer enten en streng eller ...
Men bruken av ... i TypeScript-renderingen av typen gjør det ikke klart hvor sirkulariteten eller rekursjonen er, og typen føles unøyaktig. Dette kan være et valg fra TypeScript-teamets side. Finnes det en måte å uttrykke typen mer nøyaktig på? Noe i retning av
funksjonen som når den får en valgfri strengparameter returnerer enten den tomme strengen eller typen t slik at t er typen til funksjoner som når de får en valgfri strengparameter returnerer enten en streng eller en t
Svar #1
Mens TypeScript internt kan representere anonyme rekursive typer, kan det for øyeblikket ikke serialisere dem nøyaktig. Slike typer vises i IntelliSense med ellipsen "...", som du har sett, og exporteres til deklarasjonsfiler som any. For eksempel ville din say()-funksjon produsere følgende deklarasjon:
declare function say(first?: string): "" | ((second?: string) => string | any);
// ^^^
Den eneste måten for øyeblikket å nøyaktig serialisere den typen på, ville være å gi den rekursive delen et typealias, slik at den ikke lenger er anonym og slik at du kan referere til den med navn. Du kan gjøre dette manuelt ved inspeksjon (noe som betyr at du effektivt må være din egen typekontroller); funksjonstypen din er ekvivalent med
declare function say(first?: string): SayReturn;
type SayReturn = "" | ((second?: string) => string | SayReturn);
noe som kan bekreftes ved å annotere returtypen til say med SayReturn og sørge for at ingenting bryter:
type SayReturn = "" | ((second?: string) => string | SayReturn);
function say(first?: string): SayReturn { // okay
if (first === undefined) {
return "" // okay
}
return (second?: string) => {
if (second === undefined) {
return first
}
return say(`${first} ${second}`) // okay
}
}
Det finnes en funksjonsforespørsel på microsoft/TypeScript#44045 for at TypeScript automatisk skal syntetisere et typealias for slike typer (forutsatt med et menneske-uvennlig generert navn som __Type001). Det finnes også microsoft/TypeScript#30979 som ville generere inline typealias som er lokalt avgrenset. Og det var også et forslag på microsoft/TypeScript#517 om å støtte en form for syntaks som ^ for anonyme rekursive typer. Men ingen av disse funksjonene er per nå en del av språket. Så foreløpig må du enten gi opp på serialisering eller gjøre det manuelt.
Lenke til kode på lekeplassen
