Išnagrinėkite galingus TypeScript šablonų literalinius tipus pažangiam eilučių manipuliavimui, šablonų atitikimui ir validavimui. Mokykitės su praktiniais pavyzdžiais ir realaus pasaulio naudojimo atvejais.
Šablonų Literaliniai Tipai: Eilučių Šablonų Atitikimas ir Validavimas TypeScript
TypeScript tipo sistema nuolat tobulėja, siūlydama kūrėjams galingesnius įrankius išreikšti sudėtingą logiką ir užtikrinti tipo saugumą. Viena iš įdomiausių ir universaliausių funkcijų, įdiegtų naujausiose versijose, yra šablonų literaliniai tipai. Šie tipai leidžia manipuliuoti eilutėmis tipo lygiu, įgalinant pažangų eilučių šablonų atitikimą ir validavimą. Tai atveria visiškai naują galimybių pasaulį kuriant patikimesnes ir lengviau prižiūrimas programas.
Kas yra Šablonų Literaliniai Tipai?
Šablonų literaliniai tipai yra tipo forma, kuri konstruojama derinant eilučių literalinius tipus ir sąjungos tipus, panašiai kaip šablonų literalai veikia JavaScript. Tačiau, užuot kuriant vykdymo metu eilutes, jie sukuria naujus tipus, pagrįstus esamais.
Štai pagrindinis pavyzdys:
type Greeting<T extends string> = `Hello, ${T}!`;
type MyGreeting = Greeting<"World">; // type MyGreeting = "Hello, World!"
Šiame pavyzdyje `Greeting` yra šablonų literalinis tipas, kuris kaip įvestį priima eilučių tipą `T` ir grąžina naują tipą, kuris yra "Hello, ", `T` ir "!" sujungimas.
Pagrindinis Eilučių Šablonų Atitikimas
Šablonų literaliniai tipai gali būti naudojami pagrindiniam eilučių šablonų atitikimui atlikti. Tai leidžia jums sukurti tipus, kurie yra galiojantys tik tuo atveju, jei jie atitinka tam tikrą šabloną.
Pavyzdžiui, galite sukurti tipą, kuris priima tik eilutes, prasidedančias "prefix-":
type PrefixedString<T extends string> = T extends `prefix-${string}` ? T : never;
type ValidPrefixedString = PrefixedString<"prefix-valid">; // type ValidPrefixedString = "prefix-valid"
type InvalidPrefixedString = PrefixedString<"invalid">; // type InvalidPrefixedString = never
Šiame pavyzdyje `PrefixedString` naudoja sąlyginį tipą, kad patikrintų, ar įvesties eilutė `T` prasideda "prefix-". Jei taip, tipas yra `T` pati; kitaip, tai yra `never`. `never` yra specialus tipas TypeScript, kuris atspindi reikšmių, kurios niekada neįvyksta, tipą, veiksmingai pašalinant negaliojančią eilutę.
Eilutės Dalių Išskyrimas
Šablonų literaliniai tipai taip pat gali būti naudojami eilučių dalims išskirti. Tai ypač naudinga, kai reikia išanalizuoti duomenis iš eilučių ir konvertuoti juos į skirtingus tipus.
Tarkime, kad turite eilutę, kuri atspindi koordinates formatu "x:10,y:20". Galite naudoti šablonų literalinius tipus, kad išskirtumėte x ir y reikšmes:
type CoordinateString = `x:${number},y:${number}`;
type ExtractX<T extends CoordinateString> = T extends `x:${infer X},y:${number}` ? X : never;
type ExtractY<T extends CoordinateString> = T extends `x:${number},y:${infer Y}` ? Y : never;
type XValue = ExtractX<"x:10,y:20">; // type XValue = 10
type YValue = ExtractY<"x:10,y:20">; // type YValue = 20
Šiame pavyzdyje `ExtractX` ir `ExtractY` naudoja raktinį žodį `infer`, kad užfiksuotų eilučių dalis, atitinkančias `number` tipą. `infer` leidžia išskirti tipą iš šablono atitikimo. Užfiksuoti tipai tada naudojami kaip sąlyginio tipo grąžinimo tipas.
Pažangus Eilučių Validavimas
Šablonų literaliniai tipai gali būti derinami su kitomis TypeScript funkcijomis, tokiomis kaip sąjungos tipai ir sąlyginiai tipai, kad būtų galima atlikti pažangų eilučių validavimą. Tai leidžia jums sukurti tipus, kurie užtikrina sudėtingas taisykles dėl eilučių struktūros ir turinio.
Pavyzdžiui, galite sukurti tipą, kuris validuoja ISO 8601 datos eilutes:
type Year = `${number}${number}${number}${number}`;
type Month = `0${number}` | `10` | `11` | `12`;
type Day = `${0}${number}` | `${1 | 2}${number}` | `30` | `31`;
type ISODate = `${Year}-${Month}-${Day}`;
type ValidDate = ISODate extends "2023-10-27" ? true : false; // true
type InvalidDate = ISODate extends "2023-13-27" ? true : false; // false
function processDate(date: ISODate) {
// Function logic here. TypeScript enforces the ISODate format.
return `Processing date: ${date}`;
}
console.log(processDate("2024-01-15")); // Works
//console.log(processDate("2024-1-15")); // TypeScript error: Argument of type '"2024-1-15"' is not assignable to parameter of type '`${number}${number}${number}${number}-${0}${number}-${0}${number}` | `${number}${number}${number}${number}-${0}${number}-${1}${number}` | ... 14 more ... | `${number}${number}${number}${number}-12-31`'.
Čia `Year`, `Month` ir `Day` yra apibrėžti naudojant šablonų literalinius tipus, kad atspindėtų galiojančius kiekvienos datos dalies formatus. Tada `ISODate` sujungia šiuos tipus, kad sukurtų tipą, kuris atspindi galiojančią ISO 8601 datos eilutę. Pavyzdys taip pat parodo, kaip šis tipas gali būti naudojamas duomenų formatavimui funkcijoje užtikrinti, neleidžiant perduoti neteisingų datų formatų. Tai pagerina kodo patikimumą ir apsaugo nuo vykdymo metu atsirandančių klaidų, kurias sukelia neteisinga įvestis.
Realaus Pasaulio Naudojimo Atvejai
Šablonų literaliniai tipai gali būti naudojami įvairiuose realaus pasaulio scenarijuose. Štai keli pavyzdžiai:
- Formos Validavimas: Galite naudoti šablonų literalinius tipus, kad validuotumėte formos įvesties laukų formatą, pvz., el. pašto adresus, telefono numerius ir pašto kodus.
- API Užklausų Validavimas: Galite naudoti šablonų literalinius tipus, kad validuotumėte API užklausų duomenų struktūrą, užtikrindami, kad jie atitiktų numatomą formatą. Pavyzdžiui, validuojant valiutos kodą (pvz., "USD", "EUR", "GBP").
- Konfigūracijos Failų Analizė: Galite naudoti šablonų literalinius tipus, kad analizuotumėte konfigūracijos failus ir išskirtumėte reikšmes pagal konkrečius šablonus. Apsvarstykite galimybę validuoti failų kelius konfigūracijos objekte.
- Eilutėmis Pagrįsti Enumai: Galite sukurti eilutėmis pagrįstus enumus su validavimu naudodami šablonų literalinius tipus.
Pavyzdys: Valiutos Kodų Validavimas
Pažvelkime į išsamesnį valiutos kodų validavimo pavyzdį. Norime užtikrinti, kad mūsų programoje būtų naudojami tik galiojantys ISO 4217 valiutos kodai. Šie kodai paprastai yra trys didžiosios raidės.
type CurrencyCode = `${Uppercase<string>}${Uppercase<string>}${Uppercase<string>}`;
function formatCurrency(amount: number, currency: CurrencyCode) {
// Function logic to format currency based on the provided code.
return `$${amount} ${currency}`;
}
console.log(formatCurrency(100, "USD")); // Works
//console.log(formatCurrency(100, "usd")); // TypeScript error: Argument of type '"usd"' is not assignable to parameter of type '`${Uppercase}${Uppercase}${Uppercase}`'.
//More precise example:
type ValidCurrencyCode = "USD" | "EUR" | "GBP" | "JPY" | "CAD" | "AUD"; // Extend as needed
type StronglyTypedCurrencyCode = ValidCurrencyCode;
function formatCurrencyStronglyTyped(amount: number, currency: StronglyTypedCurrencyCode) {
return `$${amount} ${currency}`;
}
console.log(formatCurrencyStronglyTyped(100, "EUR")); // Works
//console.log(formatCurrencyStronglyTyped(100, "CNY")); // TypeScript error: Argument of type '"CNY"' is not assignable to parameter of type '"USD" | "EUR" | "GBP" | "JPY" | "CAD" | "AUD"'.
Šis pavyzdys parodo, kaip sukurti `CurrencyCode` tipą, kuris priima tik eilutes, susidedančias iš trijų didžiųjų simbolių. Antrasis, labiau griežtai apibrėžtas pavyzdys parodo, kaip tai dar labiau apriboti iki iš anksto nustatyto priimtinų valiutų sąrašo.
Pavyzdys: API Galinių Taškų Kelių Validavimas
Kitas naudojimo atvejis yra API galinių taškų kelių validavimas. Galite apibrėžti tipą, kuris atspindi galiojančią API galinio taško struktūrą, užtikrindamas, kad užklausos būtų siunčiamos teisingais keliais. Tai ypač naudinga mikropaslaugų architektūrose, kai kelios paslaugos gali atverti skirtingas API.
type APIServiceName = "users" | "products" | "orders";
type APIEndpointPath = `/${APIServiceName}/${string}`;
function callAPI(path: APIEndpointPath) {
// API call logic
console.log(`Calling API: ${path}`);
}
callAPI("/users/123"); // Valid
callAPI("/products/details"); // Valid
//callAPI("/invalid/path"); // TypeScript error
// Even more specific:
type APIAction = "create" | "read" | "update" | "delete";
type APIEndpointPathSpecific = `/${APIServiceName}/${APIAction}`;
function callAPISpecific(path: APIEndpointPathSpecific) {
// API call logic
console.log(`Calling specific API: ${path}`);
}
callAPISpecific("/users/create"); // Valid
//callAPISpecific("/users/list"); // TypeScript error
Tai leidžia jums tiksliau apibrėžti API galinių taškų struktūrą, išvengiant klaidų ir užtikrinant nuoseklumą visoje jūsų programoje. Tai yra pagrindinis pavyzdys; galima sukurti sudėtingesnius šablonus, kad validuotumėte užklausos parametrus ir kitas URL dalis.
Šablonų Literalinių Tipų Naudojimo Privalumai
Šablonų literalinių tipų naudojimas eilučių šablonų atitikimui ir validavimui siūlo keletą privalumų:
- Pagerintas Tipo Saugumas: Šablonų literaliniai tipai leidžia jums primesti griežtesnius tipo apribojimus eilutėms, sumažinant klaidų riziką vykdymo metu.
- Patobulintas Kodo Skaitomumas: Šablonų literaliniai tipai padaro jūsų kodą skaitomesnį aiškiai išreikšdami numatomą eilučių formatą.
- Padidintas Priežiūros Lengvumas: Šablonų literaliniai tipai padaro jūsų kodą lengviau prižiūrimą pateikdami vieną eilučių validavimo taisyklių šaltinį.
- Geresnė Kūrėjo Patirtis: Šablonų literaliniai tipai suteikia geresnį automatinį užbaigimą ir klaidų pranešimus, pagerindami bendrą kūrėjo patirtį.
Apribojimai
Nors šablonų literaliniai tipai yra galingi, jie taip pat turi tam tikrų apribojimų:
- Sudėtingumas: Šablonų literaliniai tipai gali tapti sudėtingi, ypač kai dirbama su sudėtingais šablonais. Svarbu subalansuoti tipo saugumo naudą su kodo priežiūros lengvumu.
- Našumas: Šablonų literaliniai tipai gali turėti įtakos kompiliavimo našumui, ypač dideliuose projektuose. Taip yra todėl, kad TypeScript turi atlikti sudėtingesnį tipo tikrinimą.
- Ribotas Reguliariųjų Išraiškų Palaikymas: Nors šablonų literaliniai tipai leidžia atlikti šablonų atitikimą, jie nepalaiko viso reguliariųjų išraiškų funkcijų spektro. Labai sudėtingam eilučių validavimui, vykdymo metu reguliariosios išraiškos vis dar gali būti reikalingos kartu su šiomis tipo konstrukcijomis tinkamam įvesties valymui.
Geriausios Praktikos
Štai keletas geriausių praktikų, kurias reikia atsiminti naudojant šablonų literalinius tipus:
- Pradėkite Paprastai: Pradėkite nuo paprastų šablonų ir palaipsniui didinkite sudėtingumą, kai reikia.
- Naudokite Aprašomuosius Pavadinimus: Naudokite aprašomuosius pavadinimus savo šablonų literaliniams tipams, kad pagerintumėte kodo skaitomumą.
- Dokumentuokite Savo Tipus: Dokumentuokite savo šablonų literalinius tipus, kad paaiškintumėte jų paskirtį ir naudojimą.
- Kruopščiai Išbandykite: Kruopščiai išbandykite savo šablonų literalinius tipus, kad įsitikintumėte, jog jie veikia taip, kaip tikėtasi.
- Atsižvelkite į Našumą: Atminkite šablonų literalinių tipų poveikį kompiliavimo našumui ir atitinkamai optimizuokite savo kodą.
Išvada
Šablonų literaliniai tipai yra galinga TypeScript funkcija, leidžianti atlikti pažangų eilučių manipuliavimą, šablonų atitikimą ir validavimą tipo lygiu. Naudodami šablonų literalinius tipus, galite sukurti patikimesnes, lengviau prižiūrimas ir tipo saugias programas. Nors jie turi tam tikrų apribojimų, šablonų literalinių tipų naudojimo pranašumai dažnai nusveria trūkumus, todėl jie yra vertingas įrankis bet kurio TypeScript kūrėjo arsenale. Kadangi TypeScript kalba ir toliau tobulėja, šių pažangių tipo funkcijų supratimas ir naudojimas bus labai svarbus kuriant aukštos kokybės programinę įrangą. Nepamirškite subalansuoti sudėtingumą su skaitomumu ir visada teikite pirmenybę kruopščiam testavimui.