Poznajemy funkcję, która może wydawać nam się dziwna, ale uczy nas ona specyficznego myślenia, które przyda się w kilku miejscach. Zaczynajmy.
Ok, funkcja wygląda tak:
function strlen(str, cache = []) {
const first = str.slice(0, 1);
const rest = str.slice(1);
return first.length
? strlen(rest, [...cache, first])
: cache.length;
}
console.log(strlen("hello")); //5
Ok, pytanie pierwsze – po co? Po co rekurencyjnie, albo w jakikolwiek inny sposób, wyliczać długość stringa? Przecież każdy string posiada length…
Cóż, a w TypeScript mamy length? Mówię przed kompilacją? To tylko ćwiczenie, ma nas nauczyć specyficznego myślenia, które w TS się opłaci.
Druga rzecz, to jak – no właśnie, jak? Tworzymy pierwszą literę i resztę napisu. Wrzucamy warunek, czy pierwsza litera ma jakąś długość. Jeśli ma, to robimy rekurencyjne wywołanie na reszcie, a do kesza ładujemy pierwszą literę i to, co już w keszu.
I to tak idzie, aż w końcu first nie będzie miało żadnej litery, zaś w keszu będą jednoliterowe elementy stringu, które możemy podliczyć za pomocą length.
Wrzućmy sobie console loga dla first i rest i zobaczmy, jak to wygląda:
hello Array []
ello Array [ "h" ]
llo Array [ "h", "e" ]
lo Array(3) [ "h", "e", "l" ]
o Array(4) [ "h", "e", "l", "l" ]
<empty string> Array(5) [ "h", "e", "l", "l", "o" ]
Ok, a przykład z TSa? Cóż, przykład z TSa to ja sam jeszcze nie do końca ogarniam, ale wygląda on tak:
type Strlen<
Str extends string,
Cache extends string[] = []
> = Str extends `${infer First}${infer Rest}`
? Strlen<Rest, [...Cache, First]>
: Cache["length"]
type MyStrlen = Strlen<"hello"> // 5
//type MyStrlen = 5
I tamta poprzednia funkcja to jest zobrazowanie tak jakby tego, co tu się dzieje, tej logiki. Logikę rozumiem, nie do końca rozumiem składnię. Plus zaskoczony jestem, że można w generic type przypisać wartość tak literalnie.
Coś czuję, że w następnym odcinku TSa będzie o operatorach… Do następnego razu!