TypeScript Academy · Lektion

Rekursion på typeniveau

Gentag over typer ved hjælp af rekursive betingede typer

Lektion 3 af 413 trin

Rekursion på typeniveau er en gratis TypeScript Academy-lektion på CoddyKit. Dette er lektion 3 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i TypeScript Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. TypeScript Academy-kurset indeholder 4 lektioner i alt.

Rekursion i typer

En betinget type må referere til sig selv. Det giver typesproget løkker. Det meste rekursion på typeniveau gennemgår en tupel ét element ad gangen, fjerner hovedet og kalder sig selv på halen.

type Length<T extends unknown[]> =
  T extends [unknown, ...infer Rest]
    ? Length<Rest>
    : 0;
// (this counts down to a base case)

Basistilfældet

Al rekursion har brug for en stoppelsebetingelse. For tupler er det normalt den tomme tupel. Når mønsteret [head, ...rest] ikke længere matcher, er du nået til slutningen, og du returnerer et fast resultat.

type IsEmpty<T extends unknown[]> =
  T extends [] ? true : false;

type A = IsEmpty<[]>;     // true
type B = IsEmpty<[1, 2]>; // false

Hoved og hale

Det centrale trin er at opdele en tupel i dens første element og den resterende tupel ved at bruge infer sammen med spredningsmønsteret.

type Head<T extends unknown[]> = T extends [infer H, ...unknown[]] ? H : never;
type Tail<T extends unknown[]> = T extends [unknown, ...infer R] ? R : [];

type A = Head<[1, 2, 3]>; // 1
type B = Tail<[1, 2, 3]>; // [2, 3]

Behandling element for element

Kombinér hoved, hale og rekursion for at transformere en hel tupel. ToStrings genopbygger tupellen og erstatter hver elementtype med string.

type ToStrings<T extends unknown[]> =
  T extends [infer H, ...infer R]
    ? [string, ...ToStrings<R>]
    : [];

type A = ToStrings<[1, true, 3]>; // [string, string, string]

Akkumulatormønsteret

Ofte opbygger du et resultat i en ekstra parameter, der kaldes en akkumulator. Den starter tom og vokser for hvert trin. Det undgår, at strukturen gennemgås igen, og det er standardteknikken til løkker på typeniveau.

type Reverse<T extends unknown[], Acc extends unknown[] = []> =
  T extends [infer H, ...infer R]
    ? Reverse<R, [H, ...Acc]>
    : Acc;

type A = Reverse<[1, 2, 3]>; // [3, 2, 1]

Gennemgang af akkumulatoren

Følg Reverse<[1,2,3]>:

  • Trin 1: H=1, Acc bliver til [1]
  • Trin 2: H=2, Acc bliver til [2,1]
  • Trin 3: H=3, Acc bliver til [3,2,1]
  • Tupellen er tom, returnér Acc = [3,2,1]

Akkumulatoren fører resultatet med ned gennem hvert rekursivt kald.

type R = Reverse<["a", "b"]>; // ["b", "a"]

Rekursion over unioner

Du kan også bruge rekursion til at samle en union af strenge. Her sammenkæder vi tupelens elementer til én strengliteraltype med et skilletegn imellem.

Notation: I rigtig TypeScript skrives skabelonliteraltyper med strenge afgrænset af backtick-tegn, som indeholder dollar-krølleparentespladsholdere. I disse kodestykker viser vi mønsteret som Tpl<...>, hvor hver del angives i rækkefølge; f.eks. vises en backtick-skabelon, der matcher det bogstavelige præfiks efterfulgt af Rest, som Tpl<'prefix', infer Rest>.

type Join<T extends string[], Sep extends string = ','> =
  T extends [infer H extends string, ...infer R extends string[]]
    ? R extends []
      ? H
      : Tpl<H, Sep, Join<R, Sep>>
    : '';
// Tpl<H, Sep, ...> builds a template literal type joining the parts

type A = Join<['a', 'b', 'c']>; // 'a,b,c'

Tælling med rekursion

Rekursion kombineret med en akkumulator kan tælle. Opbyg en tupel af unknown med samme længde som inddataene, og aflæs derefter dens length. Du kommer til at bruge dette meget i aritmetikkurset.

type Count<T extends unknown[], Acc extends unknown[] = []> =
  T extends [unknown, ...infer R]
    ? Count<R, [unknown, ...Acc]>
    : Acc["length"];

type A = Count<["x", "y", "z"]>; // 3

Filtrering med rekursion

Gå en tupel igennem, og behold kun de elementer, der opfylder en betingelse, mens du fjerner resten. Spring et element over ved ikke at føje det til akkumulatoren.

type KeepStrings<T extends unknown[], Acc extends unknown[] = []> =
  T extends [infer H, ...infer R]
    ? H extends string
      ? KeepStrings<R, [...Acc, H]>
      : KeepStrings<R, Acc>
    : Acc;

type A = KeepStrings<[1, "a", 2, "b"]>; // ["a", "b"]

Grænser for rekursionsdybden

Compileren begrænser rekursionsdybden (historisk omkring 50, mens optimeringer af halerekursion i nogle mønstre tillader flere). For meget store tupler kan du ramme fejlen Typeinstansieringen er for dyb. Brug akkumulatorformen (haleformen) for at skubbe grænsen højere.

type Repeat<T, N extends number, Acc extends T[] = []> =
  Acc["length"] extends N ? Acc : Repeat<T, N, [...Acc, T]>;

type A = Repeat<0, 3>; // [0, 0, 0]

Samlet overblik

Opdeling i hoved og hale, et basistilfælde og en akkumulator er de tre ingredienser i næsten alle løkker på typeniveau. Med dem kan du afbilde, filtrere, vende, tælle og sammenføje tupler udelukkende i typesystemet.

type MapToPairs<T extends unknown[], Acc extends unknown[] = []> =
  T extends [infer H, ...infer R]
    ? MapToPairs<R, [...Acc, [H, H]]>
    : Acc;

type A = MapToPairs<[1, 2]>; // [[1, 1], [2, 2]]

Hurtig kontrol

Afprøv din forståelse af akkumulatormønsteret.

Opsummering

Nu kan du skrive løkker på typeniveau.

  • Selvrefererende betingelser skaber rekursion.
  • Opdel tupler i [H, ...R], og rekursér over halen.
  • Et basistilfælde (en tom tupel) stopper løkken.
  • En akkumulator opbygger resultatet og muliggør dyb rekursion.

Dernæst: hvordan betingelser opfører sig særligt over unioner.

Gratis at komme i gang

Lær TypeScript med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
101
Lektioner
352

Ofte stillede spørgsmål

Er lektionen “Rekursion på typeniveau” gratis?

Ja — hele teksten til “Rekursion på typeniveau” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af TypeScript Academy-kurset, skal du opgradere til CoddyKit PRO. TypeScript Academy-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “Rekursion på typeniveau”?

Gentag over typer ved hjælp af rekursive betingede typer Du øver dig i TypeScript Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på TypeScript Academy?

Der kræves ingen tidligere erfaring. TypeScript Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 3 af 4.

Hvor lang tid tager lektionen “Rekursion på typeniveau”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne TypeScript Academy-lektion?

Ja. Alle TypeScript Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Typer som beregningssprog
  2. Betingelser på typeniveau
  3. Rekursion på typeniveau
  4. Distributive betingede typer
← Tilbage til TypeScript Academy