tipuri - Extrage părți specifice dintr-o propoziție folosind cuvântul cheie infer în șiruri literale template din Typescript?


Presupunând că introducerea unei propoziții conține unul sau două spații și are structura $ {Verb}$ {one or two spaces}$ {Activity}, cum aș putea extrage Verb și Activity în Typescript?

type Split = ' ' | '  '

type ExtractVerb<S extends string> =
    S extends `${infer Verb}${Split}${infer Activity}`
    ? [Verb, Activity]
    : never;

type Verbs = ExtractVerb<"play chess" | "write  code" | "read hacker  news">

Am obținut tipul rezultat ["play", "chess"] | ["write", " code" | "code"] | ["read" | "read hacker", "hacker news" | "news"].

Așteptat: ["play", "chess"] | ["write", "code"] | ["read", "hacker news"].

Răspuns #1

Motivul pentru acest comportament este că S este o uniune, așa că orice tip care îl conține (cum ar fi $ {infer Verb}$ {Split}$ {infer Activity}) va fi considerat pentru ambii membri ai uniunii. Așadar, TypeScript îți va da ambele rezultate posibile. Pentru "write code" poți să divizezi după ' ' și să obții ["write", " code"] sau după ' ' și să obții ["write", " code"]

Ai putea să păstrezi șirurile Split într-un tuple și să le parcurgi până când obții o potrivire folosind un tip condițional recursiv:

type Split = ['  ', ' ']

type ExtractVerb<S extends string, Seprators extends string[] = Split> =
    Seprators extends [infer FirstSeparator, ...infer RestSeparators] ?
        S extends `${infer Verb}${FirstSeparator & string}${infer Activity}`
            ? [Verb, Activity]
            : ExtractVerb<S, RestSeparators & string[]>
        : never

type Verbs = ExtractVerb<"play chess" | "write  code" | "read hacker  news">

Legătură către terenul de joacă

Rețineți că acesta este un tip recursiv coadă, așa că compilatorul ar trebui să se descurce destul de bine cu el.