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.
