Búsqueda de sitios web

tipos - ¿Extraer partes específicas de una oración usando la palabra clave infer en Template Literal de Typescript?


Suponga que introducir una oración contiene uno o dos espacios y tiene la estructura $ {Verb}$ {one or two spaces}$ {Activity}, ¿cómo podría extraer el Verb y la Activity en 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">

Obtuve el tipo de resultado ["jugar", "ajedrez"] | ["escribir", "código" | "código"] | ["leer" | "leer hacker", "noticias hacker" | "noticias"].

Esperado: ["jugar", "ajedrez"] | ["escribir", "código"] | ["leer", "hacker news"].

Respuesta #1

La razón del comportamiento es que S es una unión, por lo que cualquier tipo que la contenga (como $ {infer Verb}$ {Split}$ {infer Activity}) se considerará para ambos miembros de la unión. Así que TypeScript te dará ambos resultados posibles. Para "write code" puedes dividir por ' ' y obtener ["write", " code"] o por ' ' y obtener ["write", " code"]

Podrías mantener las cadenas Split en una tupla, y recorrerlas hasta obtener una coincidencia usando un tipo condicional recursivo:

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">

Enlace del parque

Tenga en cuenta que este es un tipo recursivo de cola, por lo que el compilador debería manejarlo bastante bien.