generics - Högre ordningens typfunktioner i TypeScript?


Vänligen överväg följande pseudokod som försöker definiera en högre ordningens typfunktion med en funktions-typad parameter M<?>:

type HigherOrderTypeFn<T, M<?>> = T extends (...)
  ? M<T>
  : never;

M<?> är syntaktiskt inkorrekt TypeScript, men att deklarera typesignaturen som HigherOrderTypeFn<T, M> ger felet Type 'M' is not generic. ts(2315) på den andra raden.

Har jag rätt att anta att en sådan typ för närvarande inte kan representeras i TS?

Svar #1

Du har rätt, det är för närvarande inte representerbart i TypeScript. Det finns en långvarig öppen GitHub-förfrågan om funktionalitet, microsoft/TypeScript#1213, som förmodligen borde ha titeln något i stil med "stöd för högre ordningens typer" men för närvarande har titeln "Tillåt att klasser kan vara parametriska i andra parametriska klasser".

Det finns några idéer i diskussionen om hur man kan simulera sådana högre ordnade typer i det nuvarande språket (se den här kommentaren för ett konkret exempel), men enligt min åsikt hör de förmodligen inte hemma i produktionskod. Om du har någon specifik struktur som du försöker implementera, kanske något lämpligt kan föreslås.

Men i vilket fall, om du vill öka chansen (förmodligen försumbart, tyvärr) att detta någonsin händer, kanske du vill gå till det ärendet och ge det en 👍 och/eller beskriva ditt användningsfall om du tycker att det är särskilt övertygande jämfört med det som redan finns där. !

Svar #2

För dig och andra som söker en lösning kan du prova en enkel idé baserad på platshållare (se denna kommentar i diskussionen som nämns av jcalz):

type Placeholder = {'aUniqueKey': unknown};
type Replace<T, X, Y> = {
  [k in keyof T]: T[k] extends X ? Y : T[k];
};

Så, din funktion skulle se ut som följer:

type HigherOrderTypeFn<T, M> = T extends (...) ? Replace<M, Placeholder, T> : never;

och kallas till exempel så här:

type M<U> = U[];
type X = HigherOrderTypeFn<number, M<Placeholder>> // is number[] (if ... is number)

Relaterade artiklar