Avastage TypeScripti täiustatud funktsioone, nagu malli sõnasõnalised tüübid ja tingimuslikud tüübid, et kirjutada väljendusrikkam ja hooldatavam kood. Valdage tüüpide manipuleerimist keeruliste stsenaariumide jaoks.
TypeScripti täiustatud tüübid: malli sõnasõnaliste ja tingimuslike tüüpide valdamine
TypeScripti tugevus peitub selle võimsas tüübisüsteemis. Kuigi põhitüübid nagu string, number ja boolean on paljudes stsenaariumides piisavad, avavad täiustatud funktsioonid nagu malli sõnasõnalised tüübid ja tingimuslikud tüübid uue väljendusrikkuse ja tüübiturvalisuse taseme. See juhend annab põhjaliku ülevaate nendest täiustatud tüüpidest, uurides nende võimalusi ja demonstreerides praktilisi rakendusi.
Malli sõnasõnaliste tüüpide mõistmine
Malli sõnasõnalised tüübid põhinevad JavaScripti malli sõnasõnalisusel, võimaldades teil määratleda tüübid stringi interpolatsiooni põhjal. See võimaldab luua tüüpe, mis esindavad konkreetseid stringimustreid, muutes teie koodi tugevamaks ja ennustatavamaks.
Põhisüntaks ja kasutus
Malli sõnasõnaliste tüüpide puhul kasutatakse tüübi määratluse ümbritsemiseks tagatõkkeid (`), mis sarnaneb JavaScripti malli sõnasõnalisusega. Tagatõkete sees saate teisi tüüpe interpoleerida, kasutades süntaksit ${}. Siin juhtubki maagia – sisuliselt loote tüübi, mis on string, mis on kompileerimise ajal üles ehitatud interpolatsiooni sees olevate tüüpide põhjal.
type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE";
type APIEndpoint = `/api/${string}`;
// Example Usage
const getEndpoint: APIEndpoint = "/api/users"; // Valid
const postEndpoint: APIEndpoint = "/api/products/123"; // Valid
const invalidEndpoint: APIEndpoint = "/admin/settings"; // TypeScript ei näita siin viga, kuna `string` võib olla ükskõik mida
Selles näites on APIEndpoint tüüp, mis esindab suvalist stringi, mis algab /api/-ga. Kuigi see põhinäide on kasulik, ilmneb malli sõnasõnaliste tüüpide tõeline jõud siis, kui seda kombineeritakse spetsiifilisemate tüüpide piirangutega.
Kombineerimine liittüüpidega
Malli sõnasõnalised tüübid säravad tõeliselt siis, kui neid kasutatakse koos liittüüpidega. See võimaldab teil luua tüüpe, mis esindavad konkreetset stringi kombinatsioonide komplekti.
type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE";
type APIPath = "users" | "products" | "orders";
type APIEndpoint = `/${APIPath}/${HTTPMethod}`;
// Valid API Endpoints
const getUsers: APIEndpoint = "/users/GET";
const postProducts: APIEndpoint = "/products/POST";
// Invalid API Endpoints (will result in TypeScript errors)
// const invalidEndpoint: APIEndpoint = "/users/PATCH"; // Error: "/users/PATCH" is not assignable to type "/users/GET" | "/users/POST" | "/users/PUT" | "/users/DELETE" | "/products/GET" | "/products/POST" | ... 3 more ... | "/orders/DELETE".
Nüüd on APIEndpoint piiravama tüüp, mis lubab ainult API teede ja HTTP meetodite konkreetseid kombinatsioone. TypeScript märgistab kõik katsed kasutada kehtetuid kombinatsioone, suurendades tüübiturvalisust.
Stringi manipuleerimine malli sõnasõnaliste tüüpidega
TypeScript pakub sisemisi stringi manipuleerimise tüüpe, mis töötavad sujuvalt koos malli sõnasõnaliste tüüpidega. Need tüübid võimaldavad teil kompileerimise ajal stringe teisendada.
- Uppercase: teisendab stringi suurtähtedeks.
- Lowercase: teisendab stringi väiketähtedeks.
- Capitalize: kirjutab stringi esimese tähe suurtähtedega.
- Uncapitalize: kirjutab stringi esimese tähe väiketähtedega.
type Greeting = "hello world";
type UppercaseGreeting = Uppercase; // "HELLO WORLD"
type LowercaseGreeting = Lowercase; // "hello world"
type CapitalizedGreeting = Capitalize; // "Hello world"
type UncapitalizedGreeting = Uncapitalize; // "hello world"
Need stringi manipuleerimise tüübid on eriti kasulikud tüüpide automaatseks genereerimiseks nimekonventsioonide põhjal. Näiteks võite tuletada tegevustüübid sündmuste nimedest või vastupidi.
Malli sõnasõnaliste tüüpide praktilised rakendused
- API lõpp-punkti määratlemine: nagu eespool näidatud, API lõpp-punktide määratlemine täpsete tüüpi piirangutega.
- Sündmuste käsitlemine: tüüpide loomine sündmuste nimede jaoks konkreetsete eesliidete ja järelliidetega.
- CSS-klassi genereerimine: CSS-klassinimede genereerimine komponendi nimede ja olekute põhjal.
- Andmebaasi päringute koostamine: tüübiturvalisuse tagamine andmebaasipäringute koostamisel.
Rahvusvaheline näide: valuuta vormindamine
Kujutage ette finantsrakenduse loomist, mis toetab mitut valuutat. Saate kasutada malli sõnasõnalisi tüüpe, et tagada õige valuuta vormindamine.
type CurrencyCode = "USD" | "EUR" | "GBP" | "JPY";
type CurrencyFormat = `${number} ${T}`;
const priceUSD: CurrencyFormat<"USD"> = "100 USD"; // Valid
const priceEUR: CurrencyFormat<"EUR"> = "50 EUR"; // Valid
// const priceInvalid: CurrencyFormat<"USD"> = "100 EUR"; // Error: Type 'string' is not assignable to type '`${number} USD`'.
function formatCurrency(amount: number, currency: T): CurrencyFormat {
return `${amount} ${currency}`;
}
const formattedUSD = formatCurrency(250, "USD"); // Type: "250 USD"
const formattedEUR = formatCurrency(100, "EUR"); // Type: "100 EUR"
See näide tagab, et valuutaväärtused on alati vormindatud õige valuutakoodiga, vältides võimalikke vigu.
Tingimuslike tüüpide uurimine
Tingimuslikud tüübid toovad hargnemise loogika TypeScripti tüübisüsteemi, võimaldades teil määratleda tüüpe, mis sõltuvad teistest tüüpidest. See funktsioon on uskumatult võimas väga paindlike ja taaskasutatavate tüüpmääratluste loomiseks.
Põhisüntaks ja kasutus
Tingimuslikud tüübid kasutavad tüübi tingimuste määratlemiseks märksõna infer ja kolmikoperaatorit (condition ? trueType : falseType).
type IsString = T extends string ? true : false;
type StringCheck = IsString; // type StringCheck = true
type NumberCheck = IsString; // type NumberCheck = false
Selles näites on IsString tingimuslik tüüp, mis kontrollib, kas T on omistatav väärtusele string. Kui jah, lahendatakse tüüp väärtuseks true; vastasel juhul lahendatakse see väärtuseks false.
Märksõna infer
Märksõna infer võimaldab teil tüübi tüübist eraldada. See on eriti kasulik töötamisel keerukate tüüpidega, nagu funktsiooni tüübid või massiivitüübid.
type ReturnType any> = T extends (...args: any) => infer R ? R : any;
function add(a: number, b: number): number {
return a + b;
}
type AddReturnType = ReturnType; // type AddReturnType = number
Selles näites eraldab ReturnType funktsiooni tüübi T tagastustüübi. Tingimusliku tüübi osa infer R tuletab tagastustüübi ja omistab selle tüübimuutujale R. Kui T ei ole funktsiooni tüüp, lahendatakse tüüp väärtuseks any.
Distributiivsed tingimuslikud tüübid
Tingimuslikud tüübid muutuvad distributiivseks, kui kontrollitud tüüp on alasti tüübiparameeter. See tähendab, et tingimuslikku tüüpi rakendatakse liittüübi igale liikmele eraldi.
type ToArray = T extends any ? T[] : never;
type NumberOrStringArray = ToArray; // type NumberOrStringArray = string[] | number[]
Selles näites teisendab ToArray tüübi T massiivitüübiks. Kuna T on alasti tüübiparameeter (ei ole ümbritsetud teise tüübiga), rakendatakse tingimuslikku tüüpi eraldi number ja string kohta, mille tulemuseks on number[] ja string[] ühend.
Tingimuslike tüüpide praktilised rakendused
- Tagastustüüpide eraldamine: nagu eespool näidatud, funktsiooni tagastustüübi eraldamine.
- Tüüpide filtreerimine liidust: tüübi loomine, mis sisaldab ainult konkreetseid tüüpe liidust.
- Ülelaaditud funktsiooni tüüpide määratlemine: erinevate funktsioonitüüpide loomine sisendtüüpide põhjal.
- Tüübikaitsemehhanismide loomine: muutujatüübi kitsendavate funktsioonide määratlemine.
Rahvusvaheline näide: erinevate kuupäevavormingute käsitlemine
Maailma eri piirkondades kasutatakse erinevaid kuupäevavorminguid. Saate neid variatsioone käsitleda tingimuslike tüüpidega.
type DateFormat = "YYYY-MM-DD" | "MM/DD/YYYY" | "DD.MM.YYYY";
type ParseDate = T extends "YYYY-MM-DD"
? { year: number; month: number; day: number; format: "YYYY-MM-DD" }
: T extends "MM/DD/YYYY"
? { month: number; day: number; year: number; format: "MM/DD/YYYY" }
: T extends "DD.MM.YYYY"
? { day: number; month: number; year: number; format: "DD.MM.YYYY" }
: never;
function parseDate(dateString: string, format: T): ParseDate {
// (Implementation would handle different date formats)
if (format === "YYYY-MM-DD") {
const [year, month, day] = dateString.split("-").map(Number);
return { year, month, day, format } as ParseDate;
} else if (format === "MM/DD/YYYY") {
const [month, day, year] = dateString.split("/").map(Number);
return { month, day, year, format } as ParseDate;
} else if (format === "DD.MM.YYYY") {
const [day, month, year] = dateString.split(".").map(Number);
return { day, month, year, format } as ParseDate;
} else {
throw new Error("Invalid date format");
}
}
const parsedDateISO = parseDate("2023-10-27", "YYYY-MM-DD"); // Type: { year: number; month: number; day: number; format: "YYYY-MM-DD"; }
const parsedDateUS = parseDate("10/27/2023", "MM/DD/YYYY"); // Type: { month: number; day: number; year: number; format: "MM/DD/YYYY"; }
const parsedDateEU = parseDate("27.10.2023", "DD.MM.YYYY"); // Type: { day: number; month: number; year: number; format: "DD.MM.YYYY"; }
console.log(parsedDateISO.year); // Access the year knowing it will be there
See näide kasutab tingimuslikke tüüpe, et määratleda erinevaid kuupäeva parsimise funktsioone vastavalt määratud kuupäeva vormingule. Tüüp ParseDate tagab, et tagastatud objektil on õiged omadused vormingu põhjal.
Malli sõnasõnaliste ja tingimuslike tüüpide kombineerimine
Tõeline jõud tuleb siis, kui kombineerite malli sõnasõnalisi tüüpe ja tingimuslikke tüüpe. See võimaldab uskumatult võimsaid tüüpide manipuleerimisi.
type EventName = `on${Capitalize}`;
type ExtractEventPayload = T extends EventName
? { type: T; payload: any } // Simplified for demonstration
: never;
type ClickEvent = EventName<"click">; // "onClick"
type MouseOverEvent = EventName<"mouseOver">; // "onMouseOver"
//Example function that takes a type
function processEvent(event: T): ExtractEventPayload {
//In a real implementation, we would actually dispatch the event.
console.log(`Processing event ${event}`);
//In a real implementation, the payload would be based on event type.
return { type: event, payload: {} } as ExtractEventPayload;
}
//Note that the return types are very specific:
const clickEvent = processEvent("onClick"); // { type: "onClick"; payload: any; }
const mouseOverEvent = processEvent("onMouseOver"); // { type: "onMouseOver"; payload: any; }
//If you use other strings, you get never:
// const someOtherEvent = processEvent("someOtherEvent"); // Type is `never`
Parimad tavad ja kaalutlused
- Hoidke see lihtsana: kuigi võimsad, võivad need täiustatud tüübid kiiresti keerukaks muutuda. Püüdke selguse ja hooldatavuse poole.
- Testige põhjalikult: veenduge, et teie tüübi määratlused käituksid ootuspäraselt, kirjutades põhjalikke ühikute testid.
- Dokumenteerige oma koodi: dokumenteerige selgelt oma täiustatud tüüpide eesmärk ja käitumine, et parandada koodi loetavust.
- Arvestage jõudlusega: täiustatud tüüpide liigne kasutamine võib mõjutada kompileerimisaega. Profileerige oma koodi ja optimeerige vajadusel.
Järeldus
Malli sõnasõnalised tüübid ja tingimuslikud tüübid on võimsad tööriistad TypeScripti arsenalis. Nende täiustatud tüüpide valdamisega saate kirjutada väljendusrikkamad, hooldatavamad ja tüübiturvalised koodid. Need funktsioonid võimaldavad teil hõlmata keerulisi suhteid tüüpide vahel, kehtestada rangemaid piiranguid ja luua väga taaskasutatavaid tüübi määratlusi. Võtke need tehnikad omaks, et tõsta oma TypeScripti oskusi ja luua tugevaid ja skaleeritavaid rakendusi ülemaailmsele publikule.