Mga Pinakamahusay na Kasanayan sa Pagprograma gamit ang TypeScript
Ipinaliwanag ng artikulong ito ang mga pinakamahusay na kasanayan sa pagprograma gamit ang TypeScript.
Ipinaliwanag ng gabay na ito ang mga praktikal na pinakamahusay na kasanayan upang magamit ang mga type ng TypeScript para mabawasan ang bugs at makapagsulat ng mas nababasang code.
YouTube Video
Mga Pinakamahusay na Kasanayan sa Pagprograma gamit ang TypeScript
Ang pinakamalaking benepisyo ng TypeScript ay 'pag-iwas ng mga bug gamit ang mga type at pagpapalinaw ng layunin ng code'.
Ang mga pinakamahusay na kasanayan ay hindi lang basta mga patakaran kundi mga prinsipyo sa pagsusulat ng ligtas, nababasa, at madaling mapanatiling code. Sa ibaba, ipakikilala namin ang mga karaniwang ginagamit na pinakamahusay na kasanayan sa TypeScript na may mga praktikal na halimbawa.
Iwasan ang paggamit ng any at palaging magbigay ng makabuluhang kahulugan sa mga type
Una, tingnan natin ang punto ng 'iwasan ang paggamit ng any at magbigay ng makabuluhang mga uri.'.
Ang any ay lubusang nagtatanggal ng type checking, na nagsasawalang-bisa sa layunin ng paggamit ng TypeScript. Sa halip na gumamit ng any para lang gumana ang code, mahalagang magbigay ng mga type na mas detalyado hangga't maaari.
1// Bad
2function parse(data: any) {
3 return data.value;
4}Ang code na ito ay maaaring tumanggap ng kahit anong halaga, kaya hindi mapipigilan ang mga runtime error.
1// Good
2type ParsedData = {
3 value: string;
4};
5
6function parse(data: ParsedData): string {
7 return data.value;
8}Sa pamamagitan ng pagdedeklara ng mga type, pinapalinaw mo ang layunin ng mga input at output at pinapataas ang kaligtasan.
Palaging malinaw na ideklara ang istruktura ng object gamit ang type o interface.
Sunod, tingnan natin ang punto ng 'palaging malinaw na itakda ang estruktura ng mga object gamit ang type o interface.'.
Kung gagamitin mo ang mga object nang biglaan, maaaring malabo ang kanilang estruktura. Laging ihiwalay ang mga type para sa reusability at kadalian ng pagpapanatili.
1// Bad
2function createUser(user: { name: string; age: number }) {
3 console.log(user.name);
4}Kahit sa maliliit na bahagi ng code, mahalagang sanayin ang paghihiwalay ng mga uri (types).
1// Good
2type User = {
3 name: string;
4 age: number;
5};
6
7function createUser(user: User): void {
8 console.log(user.name);
9}Sa pagbibigay ng pangalan sa mga type, mas nagiging madali ang pag-unawa sa buong codebase.
Gamitin ang mga union type upang eksaktong mailarawan ang lahat ng posibleng estado.
Kung gagamitin mo ang simpleng string o number type para sa mga kondisyon, maaaring makalusot ang mga hindi inaasahang halaga. Sa paggamit ng union types, maaari mo lamang ipakita ang mga pinapayagang estado sa antas ng uri (type level).
1// Bad
2function setStatus(status: string) {
3 console.log(status);
4}Sa code na ito, ang mga walang saysay na string o maling halaga ay hindi natutukoy sa panahon ng compile.
1// Good
2type Status = "idle" | "loading" | "success" | "error";
3
4function setStatus(status: Status): void {
5 console.log(status);
6}Sa paggamit ng union types, maaari mong tiyak na alisin ang 'imposibleng estado' sa panahon ng compile. Bilang resulta, mapapabuti ang kaligtasan ng mga conditional branch at ang pagiging maaasahan ng code.
Tugunan ang null at undefined nang malinaw.
Sunod, tingnan natin ang punto ng 'malinaw na paghawak sa null at undefined.'.
Sa TypeScript, mahalagang ipahayag sa type kung maaaring wala ang isang value. Kung mananatiling malabo ang mga bagay, maaaring humantong ito sa runtime errors.
1type User = {
2 name: string;
3 email?: string;
4};email ay maaaring wala, kaya dapat mo itong tugunan sa ganung pag-aakala.
1function printEmail(user: User): void {
2 if (user.email) {
3 console.log(user.email);
4 }
5}Palaging suriin ang mga opsyonal na halaga bago gamitin ang mga ito.
Gamitin lang ang type assertions (as) bilang huling opsyon.
Sunod, tingnan natin ang punto ng 'huwag labis na gamitin ang type assertions.'.
Ang type assertion ay pansamantalang nilalaktawan ang type checking ng TypeScript upang ideklara na, 'Alam ko na ang halagang ito ay kabilang sa uring ito.'. Ang labis na paggamit nito ay nagpapahina sa type safety.
1// Bad
2const value = input as string;Sa code na ito, kahit hindi string ang aktuwal na halaga, walang lumalabas na error, na maaaring magdulot ng error habang tumatakbo ang programa. Tulad ng ipinapakita sa sumusunod na code, piliin muna ang ligtas na pagsusuri gamit ang type guards.
1// Good
2function isString(value: unknown): value is string {
3 return typeof value === "string";
4}
5
6if (isString(input)) {
7 console.log(input.toUpperCase());
8}Ang type guard ay mekanismo upang ligtas na matiyak ang uri habang sinusuri ang aktuwal na halaga. Sa pagbibigay-priyoridad sa type guards kaysa type assertions, mas madali mong maiiwasan ang mga error habang tumatakbo ang programa.
Huwag masyadong umasa sa type inference para sa mga return type.
Sunod, tingnan natin ang punto ng 'huwag masyadong umasa sa inference para sa mga uri ng return.'.
Malakas ang type inference ng TypeScript, ngunit mas ligtas na malinaw na tukuyin ang return type ng mga public function. Nakababawas ito ng posibleng epekto ng mga pagbabagong darating.
1// Bad
2function sum(a: number, b: number) {
3 return a + b;
4}Malinaw na ipahayag ang iyong layunin kahit sa maliliit na function.
1// Good
2function sum(a: number, b: number): number {
3 return a + b;
4}Ang pagsulat ng return type ay nagpapataas ng katatagan ng iyong API.
Tugunan ang mga input nang ligtas gamit ang unknown.
Sunod, tingnan natin ang punto ng 'ligtas na tanggapin ang panlabas na input gamit ang unknown.'.
Para sa panlabas na input tulad ng APIs, JSON, o user input, gamitin ang unknown imbis na any. Sa paggawa nito, natitiyak mong nasusuri ang lahat ng halaga at napapanatili ang kaligtasan ng uri.
1// Bad
2function handleResponse(data: any) {
3 console.log(data.id);
4}Narito kung paano mag-validate ng mga type gamit ang unknown.
1// Good
2function handleResponse(data: unknown): void {
3 if (
4 typeof data === "object" &&
5 data !== null &&
6 "id" in data
7 ) {
8 console.log((data as { id: number }).id);
9 }
10}Hindi maaaring gamitin agad ang unknown; ito ay isang uri na nangangailangan ng beripikasyon. Ito ay partikular na epektibo kapag humahawak ng panlabas na input.
Pataasin ang pagpapahayag sa pamamagitan ng pagsasama-sama ng maliliit na type.
Sunod, tingnan natin ang punto ng 'dagdagan ang pagpapahayag sa pamamagitan ng pagsasama-sama ng maliliit na uri.'.
Ang pagdedeklara ng malalaking type nang sabay-sabay ay nagpapababa ng readability at maintainability. Hatiin ang iyong mga type sa makabuluhang mga bahagi at pagsamahin ang mga ito kung kinakailangan.
1type Id = number;
2
3type UserProfile = {
4 id: Id;
5 name: string;
6};
7
8type UserWithStatus = UserProfile & {
9 status: "active" | "inactive";
10};Ang pagturing sa mga type bilang mga bahagi ay nakakatulong na ayusin ang iyong disenyo.
type at interface
Mga kalamangan ng interface
Parehong kayang magdeklara ng type ang type at interface, ngunit magkaiba ang layunin at katangian ng paggamit nila. Sa paggamit ng tama para sa bawat isa, mas malinaw ang layunin ng iyong type definitions.
1// Bad
2type User = {
3 id: number;
4 name: string;
5};
6
7type AdminUser = {
8 id: number;
9 name: string;
10 role: "admin";
11};Kung inuulit mo ang karaniwang bahagi tulad nito, nagiging marupok sa pagbabago ang iyong code.
1// Good
2interface User {
3 id: number;
4 name: string;
5}
6
7interface AdminUser extends User {
8 role: "admin";
9}Ang interface ay angkop para sa mga disenyo na nangangailangan ng extension (extends) at pinakamahusay gamitin sa pagpapahayag ng 'hugis' ng mga object.
Mga kalamangan ng type
Sa kabilang banda, ang type ay mas expressive at akma sa pagpapahayag ng union at intersection types.
1// Good
2type Status = "idle" | "loading" | "success" | "error";
3
4type ApiResponse<T> =
5 | { status: "success"; data: T }
6 | { status: "error"; message: string };Ang type ay angkop sa pagpapahayag ng mga estado, opsyon, at kombinasyon.
Mga alituntunin para sa pagpili sa pagitan ng type at interface
Bilang patakaran, gamitin ang interface para sa mga estruktura ng object at kontrata, at type naman kung kailangan mo ng expressiveness ng union, intersection, o type operations.
Pareho silang gumagana, pero mahalaga na pumili base sa kung alin ang mas malinaw na nagpapahayag ng dahilan ng type.
Isaalang-alang ang iyong mga type bilang dokumentasyon.
Panghuli, tingnan natin ang punto ng 'pagsusulat ng mga uri bilang dokumentasyon.'.
Ang mahusay na type definition ay mas maraming impormasyon kaysa sa simpleng mga komento. Mahalagang hangarin na makarating sa estado kung saan 'naiintindihan ang spesipikasyon sa pamamagitan lamang ng pagtingin sa mga uri.'.
1type ApiError = {
2 code: number;
3 message: string;
4 retryable: boolean;
5};Sa ganitong paraan, isa sa mga pangunahing lakas ng TypeScript ay ang mga type definition ay maaaring magsilbing uri ng dokumento ng spesipikasyon.
Buod
Ang pinakamahusay na kasanayan sa TypeScript ay hindi tungkol sa sobrang higpit. Ang diwa nito ay ang paglinaw ng layunin gamit ang mga type at pagsulat ng code na matibay sa harap ng pagbabago.
Sa pag-iipon ng maliliit na patakaran sa pang-araw-araw na development, makakamit mo ang mga pangmatagalang epekto tulad ng 'mas madaling review,' 'mas kaunting bug,' at 'mas madali para sa sarili at iba sa hinaharap ang pag-unawa.'.
Una, sa pag-iisip ng 'paano ko ito maipapahayag gamit ang mga type?', makakalikha ka ng de-kalidad at TypeScript na istilo ng code.
Maaari mong sundan ang artikulo sa itaas gamit ang Visual Studio Code sa aming YouTube channel. Paki-check din ang aming YouTube channel.