Tutki TypeScriptin tehokkaita mallikirjaimellisia tyyppejä edistyneeseen merkkijonojen käsittelyyn, hahmontunnistukseen ja validointiin. Opi käytännön esimerkein ja todellisilla käyttötapauksilla.
Mallikirjaimelliset tyypit: Merkkijonojen hahmontunnistus ja validointi TypeScriptissä
TypeScriptin tyyppijärjestelmä kehittyy jatkuvasti tarjoten kehittäjille tehokkaampia työkaluja monimutkaisen logiikan ilmaisemiseen ja tyyppiturvallisuuden varmistamiseen. Yksi viimeisimpien versioiden mielenkiintoisimmista ja monipuolisimmista ominaisuuksista on mallikirjaimelliset tyypit. Nämä tyypit mahdollistavat merkkijonojen käsittelyn tyyppitasolla, mikä mahdollistaa edistyneen merkkijonojen hahmontunnistuksen ja validoinnin. Tämä avaa kokonaan uuden maailman mahdollisuuksia luoda vankempia ja ylläpidettävämpiä sovelluksia.
Mitä ovat mallikirjaimelliset tyypit?
Mallikirjaimelliset tyypit ovat tyyppimuoto, joka muodostetaan yhdistämällä merkkijonokirjaimellisia tyyppejä ja unionityyppejä, samalla tavalla kuin mallikirjaimet toimivat JavaScriptissä. Sen sijaan, että luotaisiin ajonaikaisia merkkijonoja, ne luovat uusia tyyppejä olemassa olevien perusteella.
Tässä on perusesimerkki:
type Greeting<T extends string> = `Hello, ${T}!`;
type MyGreeting = Greeting<"World">; // type MyGreeting = "Hello, World!"
Tässä esimerkissä `Greeting` on mallikirjaimellinen tyyppi, joka ottaa merkkijonotyypin `T` syötteenä ja palauttaa uuden tyypin, joka on "Hello, ", `T`, ja "!" yhdistelmä.
Merkkijonojen perushahmontunnistus
Mallikirjaimellisia tyyppejä voidaan käyttää suorittamaan merkkijonojen perushahmontunnistusta. Tämä mahdollistaa sellaisten tyyppien luomisen, jotka ovat kelvollisia vain, jos ne vastaavat tiettyä hahmoa.
Voit esimerkiksi luoda tyypin, joka hyväksyy vain merkkijonoja, jotka alkavat "prefix-"-alkuliitteellä:
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
Tässä esimerkissä `PrefixedString` käyttää ehdollista tyyppiä tarkistaakseen, alkaako syöttömerkkijono `T` "prefix-"-alkuliitteellä. Jos se alkaa, tyyppi on `T` itse; muuten se on `never`. `never` on erityinen tyyppi TypeScriptissä, joka edustaa sellaisten arvojen tyyppiä, joita ei koskaan esiinny, mikä käytännössä sulkee pois virheellisen merkkijonon.
Merkkijonon osien poimiminen
Mallikirjaimellisia tyyppejä voidaan käyttää myös merkkijonon osien poimimiseen. Tämä on erityisen hyödyllistä, kun sinun on jäsennettävä tietoja merkkijonoista ja muunnettava ne eri tyypeiksi.
Oletetaan, että sinulla on merkkijono, joka edustaa koordinaattia muodossa "x:10,y:20". Voit poimia x- ja y-arvot mallikirjaimellisilla tyypeillä:
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
Tässä esimerkissä `ExtractX` ja `ExtractY` käyttävät `infer`-avainsanaa siepatakseen merkkijonon osat, jotka vastaavat `number`-tyyppiä. `infer` mahdollistaa tyypin poimimisen hahmontunnistuksesta. Siepattuja tyyppejä käytetään sitten ehdollisen tyypin palautustyyppinä.
Edistynyt merkkijonojen validointi
Mallikirjaimellisia tyyppejä voidaan yhdistää muihin TypeScript-ominaisuuksiin, kuten unionityyppeihin ja ehdollisiin tyyppeihin, edistyneen merkkijonojen validoinnin suorittamiseksi. Tämä mahdollistaa sellaisten tyyppien luomisen, jotka pakottavat monimutkaisia sääntöjä merkkijonojen rakenteelle ja sisällölle.
Voit esimerkiksi luoda tyypin, joka validoi ISO 8601 -päivämäärämerkkijonot:
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`'.
Tässä `Year`, `Month` ja `Day` on määritelty mallikirjaimellisilla tyypeillä edustamaan kunkin päivämäärän osan kelvollisia muotoja. `ISODate` sitten yhdistää nämä tyypit luodakseen tyypin, joka edustaa kelvollista ISO 8601 -päivämäärämerkkijonoa. Esimerkki myös havainnollistaa, kuinka tätä tyyppiä voidaan käyttää pakottamaan datan muotoilu funktioon, estäen väärien päivämäärämuotojen välittämisen. Tämä parantaa koodin luotettavuutta ja estää virheellisen syötteen aiheuttamia ajonaikaisia virheitä.
Todelliset käyttötapaukset
Mallikirjaimellisia tyyppejä voidaan käyttää monissa todellisissa tilanteissa. Tässä on muutamia esimerkkejä:
- Lomakevalidointi: Voit käyttää mallikirjaimellisia tyyppejä lomakkeiden syötteiden, kuten sähköpostiosoitteiden, puhelinnumeroiden ja postinumeroiden, muodon validoimiseen.
- API-pyyntöjen validointi: Voit käyttää mallikirjaimellisia tyyppejä API-pyyntöjen hyötykuormien rakenteen validoimiseen varmistaen, että ne ovat odotetun muodon mukaisia. Esimerkiksi valuuttakoodin (esim. "USD", "EUR", "GBP") validointi.
- Määritystiedostojen jäsentäminen: Voit käyttää mallikirjaimellisia tyyppejä määritystiedostojen jäsentämiseen ja arvojen poimimiseen tiettyjen hahmojen perusteella. Harkitse tiedostopolkujen validointia määritysobjektissa.
- Merkkijonopohjaiset enumit: Voit luoda merkkijonopohjaisia enumeita validoinnilla mallikirjaimellisilla tyypeillä.
Esimerkki: Valuuttakoodien validointi
Tarkastellaan tarkempaa esimerkkiä valuuttakoodien validoinnista. Haluamme varmistaa, että sovelluksessamme käytetään vain kelvollisia ISO 4217 -valuuttakoodeja. Nämä koodit ovat tyypillisesti kolme isoa kirjainta.
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"'.
Tämä esimerkki osoittaa, kuinka luodaan `CurrencyCode`-tyyppi, joka hyväksyy vain merkkijonoja, jotka koostuvat kolmesta isosta kirjaimesta. Toinen, vahvemmin tyypitetty esimerkki osoittaa, kuinka tätä voidaan rajoittaa entisestään ennalta määritettyyn luetteloon hyväksyttäviä valuuttoja.
Esimerkki: API-päätepistepolkujen validointi
Toinen käyttötapaus on API-päätepistepolkujen validointi. Voit määrittää tyypin, joka edustaa kelvollista API-päätepisterakennetta, varmistaen, että pyynnöt tehdään oikeisiin polkuihin. Tämä on erityisen hyödyllistä mikropalveluarkkitehtuureissa, joissa useat palvelut saattavat paljastaa erilaisia API:ita.
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
Tämä mahdollistaa API-päätepisteiden rakenteen määrittämisen tarkemmin, estäen kirjoitusvirheitä ja varmistaen johdonmukaisuuden sovelluksessasi. Tämä on perusesimerkki; monimutkaisempia hahmoja voidaan luoda kyselyparametrien ja URL:n muiden osien validoimiseksi.
Mallikirjaimellisten tyyppien käytön edut
Mallikirjaimellisten tyyppien käyttäminen merkkijonojen hahmontunnistukseen ja validointiin tarjoaa useita etuja:
- Parannettu tyyppiturvallisuus: Mallikirjaimelliset tyypit mahdollistavat tiukempien tyyppirajoitusten asettamisen merkkijonoille, mikä vähentää ajonaikaisten virheiden riskiä.
- Parannettu koodin luettavuus: Mallikirjaimelliset tyypit tekevät koodistasi luettavampaa ilmaisemalla selkeästi merkkijonojen odotetun muodon.
- Lisääntynyt ylläpidettävyys: Mallikirjaimelliset tyypit tekevät koodistasi ylläpidettävämpää tarjoamalla yhden totuuslähteen merkkijonojen validointisäännöille.
- Parempi kehittäjäkokemus: Mallikirjaimelliset tyypit tarjoavat paremman automaattisen täydennyksen ja virheilmoitukset, mikä parantaa yleistä kehittäjäkokemusta.
Rajoitukset
Vaikka mallikirjaimelliset tyypit ovat tehokkaita, niillä on myös joitain rajoituksia:
- Monimutkaisuus: Mallikirjaimelliset tyypit voivat muuttua monimutkaisiksi, erityisesti kun käsitellään monimutkaisia hahmoja. On tärkeää tasapainottaa tyyppiturvallisuuden edut koodin ylläpidettävyyden kanssa.
- Suorituskyky: Mallikirjaimelliset tyypit voivat vaikuttaa kääntämisen suorituskykyyn, erityisesti suurissa projekteissa. Tämä johtuu siitä, että TypeScriptin on suoritettava monimutkaisempia tyyppitarkistuksia.
- Rajoitettu säännöllisen lausekkeen tuki: Vaikka mallikirjaimelliset tyypit mahdollistavat hahmontunnistuksen, ne eivät tue kaikkia säännöllisten lausekkeiden ominaisuuksia. Erittäin monimutkaista merkkijonojen validointia varten ajonaikaisia säännöllisiä lausekkeita voidaan edelleen tarvita näiden tyyppirakenteiden rinnalla syötteen asianmukaisen puhdistamisen varmistamiseksi.
Parhaat käytännöt
Tässä on joitain parhaita käytäntöjä, jotka on hyvä pitää mielessä, kun käytät mallikirjaimellisia tyyppejä:
- Aloita yksinkertaisesti: Aloita yksinkertaisilla hahmoilla ja lisää monimutkaisuutta vähitellen tarpeen mukaan.
- Käytä kuvaavia nimiä: Käytä kuvaavia nimiä mallikirjaimellisille tyypeillesi koodin luettavuuden parantamiseksi.
- Dokumentoi tyyppisi: Dokumentoi mallikirjaimelliset tyyppisi selittääksesi niiden tarkoituksen ja käytön.
- Testaa perusteellisesti: Testaa mallikirjaimelliset tyyppisi perusteellisesti varmistaaksesi, että ne toimivat odotetusti.
- Harkitse suorituskykyä: Ole tietoinen mallikirjaimellisten tyyppien vaikutuksesta kääntämisen suorituskykyyn ja optimoi koodisi sen mukaisesti.
Johtopäätös
Mallikirjaimelliset tyypit ovat tehokas ominaisuus TypeScriptissä, jonka avulla voit suorittaa edistynyttä merkkijonojen käsittelyä, hahmontunnistusta ja validointia tyyppitasolla. Käyttämällä mallikirjaimellisia tyyppejä voit luoda vankempia, ylläpidettävämpiä ja tyyppiturvallisempia sovelluksia. Vaikka niillä on joitain rajoituksia, mallikirjaimellisten tyyppien käytön edut ylittävät usein haitat, mikä tekee niistä arvokkaan työkalun minkä tahansa TypeScript-kehittäjän arsenaalissa. TypeScript-kielen kehittyessä edelleen näiden edistyneiden tyyppiominaisuuksien ymmärtäminen ja hyödyntäminen on ratkaisevan tärkeää korkealaatuisen ohjelmiston rakentamisessa. Muista tasapainottaa monimutkaisuus luettavuuden kanssa ja priorisoi aina perusteellinen testaus.