Avastage TypeScript'i utiliittüüpide võimsus, et kirjutada puhtamat, paremini hooldatavat ja tüübikindlat koodi. Uurige praktilisi rakendusi reaalsete näidetega.
TypeScript'i utiliittüüpide valdamine: praktiline juhend globaalsetele arendajatele
TypeScript pakub võimsat komplekti sisseehitatud utiliittüüpe, mis võivad oluliselt parandada teie koodi tüübikindlust, loetavust ja hooldatavust. Need utiliittüübid on sisuliselt eelnevalt määratletud tüübimuutused, mida saate olemasolevatele tüüpidele rakendada, säästes teid korduva ja vigaderohke koodi kirjutamisest. See juhend uurib erinevaid utiliittüüpe praktiliste näidetega, mis on mõistetavad arendajatele üle kogu maailma.
Miks kasutada utiliittüüpe?
Utiliittüübid lahendavad levinud tüübimanipulatsiooni stsenaariume. Neid kasutades saate:
- Vähendage korduvkoodi: Vältige korduvate tüübimääratluste kirjutamist.
- Parandage tüübikindlust: Veenduge, et teie kood vastab tüübipiirangutele.
- Suurendage koodi loetavust: Muutke oma tüübimääratlused lühemaks ja kergemini mõistetavaks.
- Parandage hooldatavust: Lihtsustage muudatusi ja vähendage vigade tekkimise ohtu.
Põhilised utiliittüübid
Partial<T>
Partial<T>
loob tüübi, kus kõik T
omadused on muudetud valikulisteks. See on eriti kasulik, kui soovite luua tüüpi osaliste uuenduste või konfiguratsiooniobjektide jaoks.
Näide:
Kujutage ette, et ehitate e-kaubanduse platvormi klientidele erinevatest piirkondadest. Teil on Customer
tüüp:
interface Customer {
id: string;
firstName: string;
lastName: string;
email: string;
phoneNumber: string;
address: {
street: string;
city: string;
country: string;
postalCode: string;
};
preferences?: {
language: string;
currency: string;
}
}
Kliendi teabe uuendamisel ei pruugi te nõuda kõiki välju. Partial<Customer>
võimaldab teil määratleda tüübi, kus kõik Customer
omadused on valikulised:
type PartialCustomer = Partial<Customer>;
function updateCustomer(id: string, updates: PartialCustomer): void {
// ... implementatsioon kliendi uuendamiseks antud ID-ga
}
updateCustomer("123", { firstName: "John", lastName: "Doe" }); // Kehtiv
updateCustomer("456", { address: { city: "London" } }); // Kehtiv
Readonly<T>
Readonly<T>
loob tüübi, kus kõik T
omadused on muudetud kirjutuskaitstuks (readonly
), vältides muutmist pärast lähtestamist. See on väärtuslik muutumatuse tagamiseks.
Näide:
Mõelge oma globaalse rakenduse konfiguratsiooniobjektile:
interface AppConfig {
apiUrl: string;
theme: string;
supportedLanguages: string[];
version: string; // Lisatud versioon
}
const config: AppConfig = {
apiUrl: "https://api.example.com",
theme: "dark",
supportedLanguages: ["en", "fr", "de", "es", "zh"],
version: "1.0.0"
};
Et vältida konfiguratsiooni juhuslikku muutmist pärast lähtestamist, saate kasutada Readonly<AppConfig>
:
type ReadonlyAppConfig = Readonly<AppConfig>;
const readonlyConfig: ReadonlyAppConfig = {
apiUrl: "https://api.example.com",
theme: "dark",
supportedLanguages: ["en", "fr", "de", "es", "zh"],
version: "1.0.0"
};
// readonlyConfig.apiUrl = "https://newapi.example.com"; // Viga: Ei saa omistada 'apiUrl'-ile, kuna see on kirjutuskaitstud omadus.
Pick<T, K>
Pick<T, K>
loob tüübi, valides T
-st omaduste hulga K
, kus K
on string-literaalide tüüpide unioon, mis esindavad omaduste nimesid, mida soovite kaasata.
Näide:
Oletame, et teil on Event
liides erinevate omadustega:
interface Event {
id: string;
title: string;
description: string;
location: string;
startTime: Date;
endTime: Date;
organizer: string;
attendees: string[];
}
Kui vajate konkreetse kuvakomponendi jaoks ainult title
, location
ja startTime
omadusi, saate kasutada Pick
:
type EventSummary = Pick<Event, "title" | "location" | "startTime">;
function displayEventSummary(event: EventSummary): void {
console.log(`Sündmus: ${event.title} asukohas ${event.location} kell ${event.startTime}`);
}
Omit<T, K>
Omit<T, K>
loob tüübi, jättes välja T
-st omaduste hulga K
, kus K
on string-literaalide tüüpide unioon, mis esindavad omaduste nimesid, mida soovite välistada. See on vastupidine Pick
'ile.
Näide:
Kasutades sama Event
liidest, kui soovite luua tüüpi uute sündmuste loomiseks, võiksite välistada id
omaduse, mille tavaliselt genereerib taustaprogramm (backend):
type NewEvent = Omit<Event, "id">;
function createEvent(event: NewEvent): void {
// ... implementatsioon uue sündmuse loomiseks
}
Record<K, T>
Record<K, T>
loob objektitüübi, mille omaduste võtmed on K
ja mille omaduste väärtused on T
. K
võib olla string-literaalide tüüpide, number-literaalide tüüpide või sümboli unioon. See sobib ideaalselt sõnastike või kaartide loomiseks.
Näide:
Kujutage ette, et peate salvestama oma rakenduse kasutajaliidese tõlkeid. Saate kasutada Record
'i, et määratleda oma tõlgete tüüp:
type Translations = Record<string, string>;
const enTranslations: Translations = {
"hello": "Hello",
"goodbye": "Goodbye",
"welcome": "Welcome to our platform!"
};
const frTranslations: Translations = {
"hello": "Bonjour",
"goodbye": "Au revoir",
"welcome": "Bienvenue sur notre plateforme !"
};
function translate(key: string, language: string): string {
const translations = language === "en" ? enTranslations : frTranslations; //Lihtsustatud
return translations[key] || key; // Tagastab võtme, kui tõlget ei leita
}
console.log(translate("hello", "en")); // Väljund: Hello
console.log(translate("hello", "fr")); // Väljund: Bonjour
console.log(translate("nonexistent", "en")); // Väljund: nonexistent
Exclude<T, U>
Exclude<T, U>
loob tüübi, välistades T
-st kõik uniooni liikmed, mis on omistatavad U
-le. See on kasulik konkreetsete tüüpide väljafiltreerimiseks unioonist.
Näide:
Teil võib olla tüüp, mis esindab erinevaid sündmuste tüüpe:
type EventType = "concert" | "conference" | "workshop" | "webinar";
Kui soovite luua tüübi, mis välistab "webinar" sündmused, saate kasutada Exclude
'i:
type PhysicalEvent = Exclude<EventType, "webinar">;
// PhysicalEvent on nüüd "concert" | "conference" | "workshop"
function attendPhysicalEvent(event: PhysicalEvent): void {
console.log(`Osaleb füüsilisel sündmusel ${event}`);
}
// attendPhysicalEvent("webinar"); // Viga: Tüübi '"webinar"' argumenti ei saa määrata parameetrile tüübiga '"concert" | "conference" | "workshop"'.
attendPhysicalEvent("concert"); // Kehtiv
Extract<T, U>
Extract<T, U>
loob tüübi, eraldades T
-st kõik uniooni liikmed, mis on omistatavad U
-le. See on vastupidine Exclude
'ile.
Näide:
Kasutades sama EventType
'i, saate eraldada webinar'i sündmuse tüübi:
type OnlineEvent = Extract<EventType, "webinar">;
// OnlineEvent on nüüd "webinar"
function attendOnlineEvent(event: OnlineEvent): void {
console.log(`Osaleb veebisündmusel ${event}`);
}
attendOnlineEvent("webinar"); // Kehtiv
// attendOnlineEvent("concert"); // Viga: Tüübi '"concert"' argumenti ei saa määrata parameetrile tüübiga '"webinar"'.
NonNullable<T>
NonNullable<T>
loob tüübi, välistades T
-st null
ja undefined
.
Näide:
type MaybeString = string | null | undefined;
type DefinitelyString = NonNullable<MaybeString>;
// DefinitelyString on nüüd string
function processString(str: DefinitelyString): void {
console.log(str.toUpperCase());
}
// processString(null); // Viga: Tüübi 'null' argumenti ei saa määrata parameetrile tüübiga 'string'.
// processString(undefined); // Viga: Tüübi 'undefined' argumenti ei saa määrata parameetrile tüübiga 'string'.
processString("hello"); // Kehtiv
ReturnType<T>
ReturnType<T>
loob tüübi, mis koosneb funktsiooni T
tagastustüübist.
Näide:
function greet(name: string): string {
return `Hello, ${name}!`;
}
type Greeting = ReturnType<typeof greet>;
// Greeting on nüüd string
const message: Greeting = greet("World");
console.log(message);
Parameters<T>
Parameters<T>
loob korteežitüübi funktsioonitüübi T
parameetrite tüüpidest.
Näide:
function logEvent(eventName: string, eventData: object): void {
console.log(`Sündmus: ${eventName}`, eventData);
}
type LogEventParams = Parameters<typeof logEvent>;
// LogEventParams on nüüd [eventName: string, eventData: object]
const params: LogEventParams = ["user_login", { userId: "123", timestamp: Date.now() }];
logEvent(...params);
ConstructorParameters<T>
ConstructorParameters<T>
loob korteeži- või massiivitüübi konstruktorfunktsiooni tüübi T
parameetrite tüüpidest. See järeldab argumentide tüübid, mis tuleb edastada klassi konstruktorile.
Näide:
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}
type GreeterParams = ConstructorParameters<typeof Greeter>;
// GreeterParams on nüüd [message: string]
const paramsGreeter: GreeterParams = ["World"];
const greeterInstance = new Greeter(...paramsGreeter);
console.log(greeterInstance.greet()); // Väljund: Hello, World
Required<T>
Required<T>
loob tüübi, mis koosneb kõigist T
omadustest, mis on määratud kohustuslikuks. See muudab kõik valikulised omadused kohustuslikuks.
Näide:
interface UserProfile {
name: string;
age?: number;
email?: string;
}
type RequiredUserProfile = Required<UserProfile>;
// RequiredUserProfile on nüüd { name: string; age: number; email: string; }
const completeProfile: RequiredUserProfile = {
name: "Alice",
age: 30,
email: "alice@example.com"
};
// const incompleteProfile: RequiredUserProfile = { name: "Bob" }; // Viga: Omadus 'age' on puudu tüübis '{ name: string; }', kuid on nõutud tüübis 'Required'.
Täpsemad utiliittüübid
Mall-literaalide tüübid
Mall-literaalide tüübid võimaldavad teil luua uusi string-literaalide tüüpe, ühendades olemasolevaid string-literaalide tüüpe, number-literaalide tüüpe ja muud. See võimaldab võimsat stringipõhist tüübimanipulatsiooni.
Näide:
type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE";
type APIEndpoint = `/api/users` | `/api/products`;
type RequestURL = `${HTTPMethod} ${APIEndpoint}`;
// RequestURL on nüüd "GET /api/users" | "POST /api/users" | "PUT /api/users" | "DELETE /api/users" | "GET /api/products" | "POST /api/products" | "PUT /api/products" | "DELETE /api/products"
function makeRequest(url: RequestURL): void {
console.log(`Päringu tegemine aadressile ${url}`);
}
makeRequest("GET /api/users"); // Kehtiv
// makeRequest("INVALID /api/users"); // Viga
Tingimuslikud tüübid
Tingimuslikud tüübid võimaldavad teil määratleda tüüpe, mis sõltuvad tüübisuhtena väljendatud tingimusest. Nad kasutavad infer
võtmesõna tüübiinfo eraldamiseks.
Näide:
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
// Kui T on Promise, siis on tüüp U; vastasel juhul on tüüp T.
async function fetchData(): Promise<number> {
return 42;
}
type Data = UnwrapPromise<ReturnType<typeof fetchData>>;
// Data on nüüd number
function processData(data: Data): void {
console.log(data * 2);
}
processData(await fetchData());
Praktilised rakendused ja reaalsed stsenaariumid
Uurime keerukamaid reaalseid stsenaariume, kus utiliittüübid säravad.
1. Vormide käsitlemine
Vormidega tegelemisel on teil sageli stsenaariume, kus peate esindama vormi algväärtusi, uuendatud vormi väärtusi ja lõplikke esitatud väärtusi. Utiliittüübid aitavad teil neid erinevaid olekuid tõhusalt hallata.
interface FormData {
firstName: string;
lastName: string;
email: string;
country: string; // Nõutud
city?: string; // Valikuline
postalCode?: string;
newsletterSubscription?: boolean;
}
// Vormi algväärtused (valikulised väljad)
type InitialFormValues = Partial<FormData>;
// Uuendatud vormi väärtused (mõned väljad võivad puududa)
type UpdatedFormValues = Partial<FormData>;
// Esitamiseks nõutavad väljad
type RequiredForSubmission = Required<Pick<FormData, 'firstName' | 'lastName' | 'email' | 'country'>>;
// Kasutage neid tüüpe oma vormikomponentides
function initializeForm(initialValues: InitialFormValues): void { }
function updateForm(updates: UpdatedFormValues): void {}
function submitForm(data: RequiredForSubmission): void {}
const initialForm: InitialFormValues = { newsletterSubscription: true };
const updateFormValues: UpdatedFormValues = {
firstName: "John",
lastName: "Doe"
};
// const submissionData: RequiredForSubmission = { firstName: "test", lastName: "test", email: "test" }; // VIGA: Puudub 'country'
const submissionData: RequiredForSubmission = { firstName: "test", lastName: "test", email: "test", country: "USA" }; //OK
2. API andmete teisendamine
API-st andmete tarbimisel peate võib-olla andmed oma rakenduse jaoks teise vormingusse teisendama. Utiliittüübid aitavad teil määratleda teisendatud andmete struktuuri.
interface APIResponse {
user_id: string;
first_name: string;
last_name: string;
email_address: string;
profile_picture_url: string;
is_active: boolean;
}
// Teisendage API vastus loetavamasse vormingusse
type UserData = {
id: string;
fullName: string;
email: string;
avatar: string;
active: boolean;
};
function transformApiResponse(response: APIResponse): UserData {
return {
id: response.user_id,
fullName: `${response.first_name} ${response.last_name}`,
email: response.email_address,
avatar: response.profile_picture_url,
active: response.is_active
};
}
function fetchAndTransformData(url: string): Promise<UserData> {
return fetch(url)
.then(response => response.json())
.then(data => transformApiResponse(data));
}
// Saate isegi tüübi jõustada, tehes järgmist:
function saferTransformApiResponse(response: APIResponse): UserData {
const {user_id, first_name, last_name, email_address, profile_picture_url, is_active} = response;
const transformed: UserData = {
id: user_id,
fullName: `${first_name} ${last_name}`,
email: email_address,
avatar: profile_picture_url,
active: is_active
};
return transformed;
}
3. Konfiguratsiooniobjektide käsitlemine
Konfiguratsiooniobjektid on paljudes rakendustes tavalised. Utiliittüübid aitavad teil määratleda konfiguratsiooniobjekti struktuuri ja tagada, et seda kasutatakse õigesti.
interface AppSettings {
theme: "light" | "dark";
language: string;
notificationsEnabled: boolean;
apiUrl?: string; // Valikuline API URL erinevate keskkondade jaoks
timeout?: number; //Valikuline
}
// Vaikeseaded
const defaultSettings: AppSettings = {
theme: "light",
language: "en",
notificationsEnabled: true
};
// Funktsioon kasutaja seadete ühendamiseks vaikeseadetega
function mergeSettings(userSettings: Partial<AppSettings>): AppSettings {
return { ...defaultSettings, ...userSettings };
}
// Kasutage ühendatud seadeid oma rakenduses
const mergedSettings = mergeSettings({ theme: "dark", apiUrl: "https://customapi.example.com" });
console.log(mergedSettings);
Nõuanded utiliittüüpide tõhusaks kasutamiseks
- Alustage lihtsalt: Alustage põhiliste utiliittüüpidega nagu
Partial
jaReadonly
, enne kui liigute keerukamate juurde. - Kasutage kirjeldavaid nimesid: Andke oma tüübialiasele tähendusrikkaid nimesid loetavuse parandamiseks.
- Kombineerige utiliittüüpe: Keerukate tüübimuutuste saavutamiseks saate kombineerida mitut utiliittüüpi.
- Kasutage redaktori tuge: Kasutage ära TypeScripti suurepärast redaktori tuge, et uurida utiliittüüpide mõju.
- Mõistke aluspõhimõtteid: TypeScripti tüübisüsteemi põhjalik mõistmine on utiliittüüpide tõhusaks kasutamiseks hädavajalik.
Kokkuvõte
TypeScript'i utiliittüübid on võimsad tööriistad, mis võivad oluliselt parandada teie koodi kvaliteeti ja hooldatavust. Mõistes ja rakendades neid utiliittüüpe tõhusalt, saate kirjutada puhtamaid, tüübikindlamaid ja robustsemaid rakendusi, mis vastavad globaalse arendusmaastiku nõudmistele. See juhend on andnud põhjaliku ülevaate levinud utiliittüüpidest ja praktilistest näidetest. Katsetage nendega ja uurige nende potentsiaali oma TypeScripti projektide täiustamiseks. Pidage meeles, et utiliittüüpide kasutamisel tuleb eelistada loetavust ja selgust ning püüda alati kirjutada koodi, mis on kergesti mõistetav ja hooldatav, olenemata sellest, kus teie kaastöötajad asuvad.