Izpētiet tipu aizsargus un tipu apgalvojumus TypeScript, lai uzlabotu tipu drošību, novērstu izpildlaika kļūdas un rakstītu stabilāku un uzturamāku kodu. Mācieties ar praktiskiem piemēriem un labāko praksi.
Tipu drošības apgūšana: Visaptverošs ceļvedis par tipu aizsargiem un tipu apgalvojumiem
Programmatūras izstrādes jomā, īpaši strādājot ar dinamiski tipizētām valodām, piemēram, JavaScript, tipu drošības uzturēšana var būt ievērojams izaicinājums. TypeScript, kas ir JavaScript virskopa, risina šo problēmu, ieviešot statisko tipizēšanu. Tomēr pat ar TypeScript tipu sistēmu rodas situācijas, kad kompilatoram nepieciešama palīdzība, lai secinātu pareizo mainīgā tipu. Tieši šeit spēlē ienāk tipu aizsargi un tipu apgalvojumi. Šis visaptverošais ceļvedis iedziļināsies šajās jaudīgajās funkcijās, sniedzot praktiskus piemērus un labāko praksi, lai uzlabotu jūsu koda uzticamību un uzturamību.
Kas ir tipu aizsargi?
Tipu aizsargi ir TypeScript izteiksmes, kas sašaurina mainīgā tipu noteiktā darbības jomā. Tie ļauj kompilatoram precīzāk izprast mainīgā tipu, nekā tas sākotnēji tika secināts. Tas ir īpaši noderīgi, strādājot ar apvienojuma tipiem (union types) vai kad mainīgā tips ir atkarīgs no izpildlaika nosacījumiem. Izmantojot tipu aizsargus, jūs varat izvairīties no izpildlaika kļūdām un rakstīt stabilāku kodu.
Izplatītākās tipu aizsargu tehnikas
TypeScript nodrošina vairākus iebūvētus mehānismus tipu aizsargu izveidei:
typeof
operators: Pārbauda mainīgā primitīvo tipu (piemēram, "string", "number", "boolean", "undefined", "object", "function", "symbol", "bigint").instanceof
operators: Pārbauda, vai objekts ir konkrētas klases instance.in
operators: Pārbauda, vai objektam ir konkrēta īpašība.- Pielāgotas tipu aizsargu funkcijas: Funkcijas, kas atgriež tipa predikātu, kas ir īpašs Būla izteiksmes veids, ko TypeScript izmanto tipu sašaurināšanai.
typeof
izmantošana
typeof
operators ir vienkāršs veids, kā pārbaudīt mainīgā primitīvo tipu. Tas atgriež virkni, kas norāda tipu.
function printValue(value: string | number) {
if (typeof value === "string") {
console.log(value.toUpperCase()); // TypeScript šeit zina, ka 'value' ir virkne
} else {
console.log(value.toFixed(2)); // TypeScript šeit zina, ka 'value' ir skaitlis
}
}
printValue("hello"); // Izsaukums: HELLO
printValue(3.14159); // Izsaukums: 3.14
instanceof
izmantošana
instanceof
operators pārbauda, vai objekts ir konkrētas klases instance. Tas ir īpaši noderīgi, strādājot ar mantošanu.
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
}
class Dog extends Animal {
bark() {
console.log("Woof!");
}
}
function makeSound(animal: Animal) {
if (animal instanceof Dog) {
animal.bark(); // TypeScript šeit zina, ka 'animal' ir suns (Dog)
} else {
console.log("Vispārēja dzīvnieka skaņa");
}
}
const myDog = new Dog("Buddy");
const myAnimal = new Animal("Generic Animal");
makeSound(myDog); // Izsaukums: Woof!
makeSound(myAnimal); // Izsaukums: Vispārēja dzīvnieka skaņa
in
izmantošana
in
operators pārbauda, vai objektam ir konkrēta īpašība. Tas ir noderīgi, strādājot ar objektiem, kuriem var būt dažādas īpašības atkarībā no to tipa.
interface Bird {
fly(): void;
layEggs(): void;
}
interface Fish {
swim(): void;
layEggs(): void;
}
function move(animal: Bird | Fish) {
if ("fly" in animal) {
animal.fly(); // TypeScript šeit zina, ka 'animal' ir putns (Bird)
} else {
animal.swim(); // TypeScript šeit zina, ka 'animal' ir zivs (Fish)
}
}
const myBird: Bird = { fly: () => console.log("Lido"), layEggs: () => console.log("Dēj olas") };
const myFish: Fish = { swim: () => console.log("Peld"), layEggs: () => console.log("Dēj olas") };
move(myBird); // Izsaukums: Lido
move(myFish); // Izsaukums: Peld
Pielāgotas tipu aizsargu funkcijas
Sarežģītākiem scenārijiem varat definēt savas tipu aizsargu funkcijas. Šīs funkcijas atgriež tipa predikātu, kas ir Būla izteiksme, ko TypeScript izmanto, lai sašaurinātu mainīgā tipu. Tipa predikāts ir formā mainīgais is Tips
.
interface Square {
kind: "square";
size: number;
}
interface Circle {
kind: "circle";
radius: number;
}
type Shape = Square | Circle;
function isSquare(shape: Shape): shape is Square {
return shape.kind === "square";
}
function getArea(shape: Shape) {
if (isSquare(shape)) {
return shape.size * shape.size; // TypeScript šeit zina, ka 'shape' ir kvadrāts (Square)
} else {
return Math.PI * shape.radius * shape.radius; // TypeScript šeit zina, ka 'shape' ir aplis (Circle)
}
}
const mySquare: Square = { kind: "square", size: 5 };
const myCircle: Circle = { kind: "circle", radius: 3 };
console.log(getArea(mySquare)); // Izsaukums: 25
console.log(getArea(myCircle)); // Izsaukums: 28.274333882308138
Kas ir tipu apgalvojumi?
Tipu apgalvojumi ir veids, kā paziņot TypeScript kompilatoram, ka jūs zināt vairāk par mainīgā tipu, nekā tas pašlaik saprot. Tas ir veids, kā ignorēt TypeScript tipu secināšanu un skaidri norādīt vērtības tipu. Tomēr ir svarīgi lietot tipu apgalvojumus piesardzīgi, jo tie var apiet TypeScript tipu pārbaudi un, nepareizi lietojot, var novest pie izpildlaika kļūdām.
Tipu apgalvojumiem ir divas formas:
- Leņķiekavu sintakse:
<Type>value
as
atslēgvārds:value as Type
as
atslēgvārds parasti ir ieteicamāks, jo tas ir labāk saderīgs ar JSX.
Kad lietot tipu apgalvojumus
Tipu apgalvojumus parasti izmanto šādos scenārijos:
- Kad esat pārliecināts par mainīgā tipu, ko TypeScript nevar secināt.
- Strādājot ar kodu, kas mijiedarbojas ar JavaScript bibliotēkām, kuras nav pilnībā tipizētas.
- Kad nepieciešams konvertēt vērtību uz specifiskāku tipu.
Tipu apgalvojumu piemēri
Skaidrs tipa apgalvojums
Šajā piemērā mēs apgalvojam, ka document.getElementById
izsaukums atgriezīs HTMLCanvasElement
. Bez apgalvojuma TypeScript secinātu vispārīgāku tipu HTMLElement | null
.
const canvas = document.getElementById("myCanvas") as HTMLCanvasElement;
const ctx = canvas.getContext("2d"); // TypeScript šeit zina, ka 'canvas' ir HTMLCanvasElement
if (ctx) {
ctx.fillStyle = "#FF0000";
ctx.fillRect(0, 0, 150, 75);
}
Darbs ar nezināmiem tipiem
Strādājot ar datiem no ārēja avota, piemēram, API, jūs varat saņemt datus ar nezināmu tipu. Varat izmantot tipa apgalvojumu, lai paziņotu TypeScript, kā apstrādāt datus.
interface User {
id: number;
name: string;
email: string;
}
async function fetchUser(id: number): Promise<User> {
const response = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`);
const data = await response.json();
return data as User; // Apgalvojam, ka dati ir lietotājs (User)
}
fetchUser(1)
.then(user => {
console.log(user.name); // TypeScript šeit zina, ka 'user' ir lietotājs (User)
})
.catch(error => {
console.error("Kļūda, ielādējot lietotāju:", error);
});
Piesardzības pasākumi, lietojot tipu apgalvojumus
Tipu apgalvojumi jālieto taupīgi un piesardzīgi. Pārmērīga tipu apgalvojumu lietošana var maskēt pamatā esošās tipu kļūdas un izraisīt izpildlaika problēmas. Šeit ir daži galvenie apsvērumi:
- Izvairieties no piespiedu apgalvojumiem: Neizmantojiet tipu apgalvojumus, lai piespiestu vērtību tipam, kas tai acīmredzami nav. Tas var apiet TypeScript tipu pārbaudi un novest pie neparedzētas darbības.
- Dodiet priekšroku tipu aizsargiem: Kad vien iespējams, izmantojiet tipu aizsargus, nevis tipu apgalvojumus. Tipu aizsargi nodrošina drošāku un uzticamāku veidu, kā sašaurināt tipus.
- Validējiet datus: Ja apgalvojat datu tipu no ārēja avota, apsveriet iespēju validēt datus pret shēmu, lai nodrošinātu, ka tie atbilst gaidītajam tipam.
Tipu sašaurināšana
Tipu aizsargi ir cieši saistīti ar tipu sašaurināšanas jēdzienu. Tipu sašaurināšana ir process, kurā mainīgā tips tiek precizēts līdz specifiskākam tipam, pamatojoties uz izpildlaika nosacījumiem vai pārbaudēm. Tipu aizsargi ir rīki, ko mēs izmantojam, lai panāktu tipu sašaurināšanu.
TypeScript izmanto kontroles plūsmas analīzi, lai saprastu, kā mainīgā tips mainās dažādos koda zaros. Kad tiek izmantots tipu aizsargs, TypeScript atjaunina savu iekšējo izpratni par mainīgā tipu, ļaujot jums droši izmantot metodes un īpašības, kas ir specifiskas šim tipam.
Tipu sašaurināšanas piemērs
function processValue(value: string | number | null) {
if (value === null) {
console.log("Vērtība ir null");
} else if (typeof value === "string") {
console.log(value.toUpperCase()); // TypeScript šeit zina, ka 'value' ir virkne
} else {
console.log(value.toFixed(2)); // TypeScript šeit zina, ka 'value' ir skaitlis
}
}
processValue("test"); // Izsaukums: TEST
processValue(123.456); // Izsaukums: 123.46
processValue(null); // Izsaukums: Vērtība ir null
Labākā prakse
Lai efektīvi izmantotu tipu aizsargus un tipu apgalvojumus savos TypeScript projektos, apsveriet šādu labāko praksi:
- Dodiet priekšroku tipu aizsargiem, nevis tipu apgalvojumiem: Tipu aizsargi nodrošina drošāku un uzticamāku veidu, kā sašaurināt tipus. Izmantojiet tipu apgalvojumus tikai tad, kad tas ir nepieciešams, un dariet to piesardzīgi.
- Izmantojiet pielāgotas tipu aizsargu funkcijas sarežģītiem scenārijiem: Strādājot ar sarežģītām tipu attiecībām vai pielāgotām datu struktūrām, definējiet savas tipu aizsargu funkcijas, lai uzlabotu koda skaidrību un uzturamību.
- Dokumentējiet tipu apgalvojumus: Ja izmantojat tipu apgalvojumus, pievienojiet komentārus, lai paskaidrotu, kāpēc tos izmantojat un kāpēc uzskatāt, ka apgalvojums ir drošs.
- Validējiet ārējos datus: Strādājot ar datiem no ārējiem avotiem, validējiet datus pret shēmu, lai nodrošinātu, ka tie atbilst gaidītajam tipam. Šim nolūkam var noderēt tādas bibliotēkas kā
zod
vaiyup
. - Uzturiet precīzas tipu definīcijas: Pārliecinieties, ka jūsu tipu definīcijas precīzi atspoguļo jūsu datu struktūru. Neprecīzas tipu definīcijas var novest pie nepareiziem tipu secinājumiem un izpildlaika kļūdām.
- Iespējojiet stingro režīmu (Strict Mode): Izmantojiet TypeScript stingro režīmu (
strict: true
failātsconfig.json
), lai iespējotu stingrāku tipu pārbaudi un laicīgi atklātu potenciālās kļūdas.
Starptautiskie apsvērumi
Izstrādājot lietojumprogrammas globālai auditorijai, ir jāapzinās, kā tipu aizsargi un tipu apgalvojumi var ietekmēt lokalizācijas un internacionalizācijas (i18n) centienus. Konkrēti, apsveriet:
- Datu formatēšana: Skaitļu un datumu formāti ievērojami atšķiras dažādās lokalizācijās. Veicot tipu pārbaudes vai apgalvojumus par skaitliskām vai datuma vērtībām, nodrošiniet, ka izmantojat lokalizācijai pielāgotas formatēšanas un parsēšanas funkcijas. Piemēram, izmantojiet tādas bibliotēkas kā
Intl.NumberFormat
unIntl.DateTimeFormat
, lai formatētu un parsētu skaitļus un datumus atbilstoši lietotāja lokalizācijai. Nepareizs pieņēmums par konkrētu formātu (piemēram, ASV datuma formātu MM/DD/YYYY) var izraisīt kļūdas citās lokalizācijās. - Valūtas apstrāde: Valūtu simboli un formatēšana arī globāli atšķiras. Strādājot ar naudas vērtībām, izmantojiet bibliotēkas, kas atbalsta valūtas formatēšanu un konvertēšanu, un izvairieties no valūtu simbolu cietkodēšanas. Pārliecinieties, ka jūsu tipu aizsargi pareizi apstrādā dažādus valūtu tipus un novērš nejaušu valūtu sajaukšanos.
- Rakstzīmju kodēšana: Apzinieties rakstzīmju kodēšanas problēmas, īpaši strādājot ar virknēm. Pārliecinieties, ka jūsu kods pareizi apstrādā Unicode rakstzīmes un izvairās no pieņēmumiem par rakstzīmju kopām. Apsveriet iespēju izmantot bibliotēkas, kas nodrošina Unicode atbalstošas virkņu manipulācijas funkcijas.
- No labās uz kreiso pusi (RTL) rakstāmas valodas: Ja jūsu lietojumprogramma atbalsta RTL valodas, piemēram, arābu vai ivritu, pārliecinieties, ka jūsu tipu aizsargi un apgalvojumi pareizi apstrādā teksta virzienu. Pievērsiet uzmanību tam, kā RTL teksts varētu ietekmēt virkņu salīdzināšanu un validāciju.
Noslēgums
Tipu aizsargi un tipu apgalvojumi ir būtiski rīki tipu drošības uzlabošanai un stabilāka TypeScript koda rakstīšanai. Izprotot, kā efektīvi izmantot šīs funkcijas, jūs varat novērst izpildlaika kļūdas, uzlabot koda uzturamību un izveidot uzticamākas lietojumprogrammas. Atcerieties dot priekšroku tipu aizsargiem, nevis tipu apgalvojumiem, kad vien iespējams, dokumentēt savus tipu apgalvojumus un validēt ārējos datus, lai nodrošinātu tipu informācijas precizitāti. Šo principu piemērošana ļaus jums izveidot stabilāku un paredzamāku programmatūru, kas piemērota izvietošanai visā pasaulē.