Tìm kiếm trang web

các loại - Trích xuất các phần cụ thể từ câu bằng cách sử dụng từ khóa infer trong Template Literal của Typescript?


Giả sử việc nhập một câu chứa một hoặc hai khoảng trắng và có cấu trúc $ {Verb}$ {một hoặc hai khoảng trắng}$ {Activity}, làm thế nào tôi có thể trích xuất Verb và Activity trong 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">

Tôi nhận được kiểu kết quả ["play", "chess"] | ["write", " code" | "code"] | ["read" | "read hacker", "hacker news" | "news"].

Dự kiến: ["chơi", "cờ"] | ["viết", "mã"] | ["đọc", "tin tức hacker"].

Câu trả lời #1

Nguyên nhân của hành vi này là vì S là một kiểu hợp, nên bất kỳ kiểu nào chứa nó (chẳng hạn như ${infer Verb}${Split}${infer Activity}) sẽ được xem xét cho cả hai thành viên của hợp. Vì vậy, TypeScript sẽ cung cấp cho bạn cả hai kết quả khả dĩ. Đối với "write code", bạn có thể tách bằng ' ' và nhận được ["write", " code"] hoặc tách bằng ' ' và nhận được ["write", " code"].

Bạn có thể giữ các chuỗi Split trong một tuple, và chạy qua chúng cho đến khi bạn tìm được một kết quả phù hợp bằng cách sử dụng một loại điều kiện đệ quy:

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

Liên kết Sân chơi

Lưu ý rằng đây là một loại đệ quy đuôi, vì vậy trình biên dịch nên xử lý nó khá tốt.