Atklājiet TypeScript utilītu tipu spēku, lai rakstītu tīrāku, vieglāk uzturamu un tipdrošu kodu. Izpētiet praktiskus pielietojumus ar reāliem piemēriem izstrādātājiem visā pasaulē.
TypeScript utilītu tipu apgūšana: praktisks ceļvedis globāliem izstrādātājiem
TypeScript piedāvā spēcīgu iebūvētu utilītu tipu kopumu, kas var ievērojami uzlabot jūsu koda tipu drošību, lasāmību un uzturamību. Šie utilītu tipi būtībā ir iepriekš definētas tipu transformācijas, kuras varat piemērot esošajiem tipiem, tādējādi ietaupot jūs no atkārtota un kļūdu pakļāvīga koda rakstīšanas. Šajā rokasgrāmatā tiks pētīti dažādi utilītu tipi ar praktiskiem piemēriem, kas rezonē ar izstrādātājiem visā pasaulē.
Kāpēc izmantot utilītu tipus?
Utilītu tipi risina izplatītus tipu manipulācijas scenārijus. Izmantojot tos, jūs varat:
- Samazināt šablonu kodu: Izvairieties no atkārtotu tipu definīciju rakstīšanas.
- Uzlabot tipu drošību: Pārliecinieties, ka jūsu kods atbilst tipu ierobežojumiem.
- Uzlabot koda lasāmību: Padariet savas tipu definīcijas kodolīgākas un vieglāk saprotamas.
- Palielināt uzturamību: Vienkāršojiet modifikācijas un samaziniet kļūdu ieviešanas risku.
Galvenie utilītu tipi
Partial
Partial
konstruē tipu, kurā visi T
rekvizīti ir iestatīti kā neobligāti. Tas ir īpaši noderīgi, ja vēlaties izveidot tipu daļējiem atjauninājumiem vai konfigurācijas objektiem.
Piemērs:
Iedomājieties, ka veidojat e-komercijas platformu ar klientiem no dažādiem reģioniem. Jums ir Customer
tips:
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;
}
}
Atjauninot klienta informāciju, iespējams, nevēlaties pieprasīt visus laukus. Partial
ļauj definēt tipu, kurā visi Customer
rekvizīti ir neobligāti:
type PartialCustomer = Partial<Customer>;
function updateCustomer(id: string, updates: PartialCustomer): void {
// ... ieviešana, lai atjauninātu klientu ar norādīto ID
}
updateCustomer("123", { firstName: "John", lastName: "Doe" }); // Derīgs
updateCustomer("456", { address: { city: "London" } }); // Derīgs
Readonly
Readonly
konstruē tipu, kurā visi T
rekvizīti ir iestatīti uz readonly
, novēršot modifikācijas pēc inicializācijas. Tas ir vērtīgi, lai nodrošinātu nemainīgumu.
Piemērs:
Apsveriet konfigurācijas objektu savai globālajai lietojumprogrammai:
interface AppConfig {
apiUrl: string;
theme: string;
supportedLanguages: string[];
version: string; // Pievienota versija
}
const config: AppConfig = {
apiUrl: "https://api.example.com",
theme: "dark",
supportedLanguages: ["en", "fr", "de", "es", "zh"],
version: "1.0.0"
};
Lai novērstu nejaušu konfigurācijas modifikāciju pēc inicializācijas, varat izmantot Readonly
:
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"; // Kļūda: Nevar piešķirt vērtību rekvizītam 'apiUrl', jo tas ir tikai lasāms rekvizīts.
Pick
Pick
konstruē tipu, izvēloties rekvizītu kopu K
no T
, kur K
ir virknes literāļu tipu apvienojums, kas apzīmē rekvizītu nosaukumus, kurus vēlaties iekļaut.
Piemērs:
Pieņemsim, ka jums ir Event
interfeiss ar dažādiem rekvizītiem:
interface Event {
id: string;
title: string;
description: string;
location: string;
startTime: Date;
endTime: Date;
organizer: string;
attendees: string[];
}
Ja jums ir nepieciešams tikai title
, location
un startTime
konkrētam displeja komponentam, varat izmantot Pick
:
type EventSummary = Pick<Event, "title" | "location" | "startTime">;
function displayEventSummary(event: EventSummary): void {
console.log(`Pasākums: ${event.title} at ${event.location} on ${event.startTime}`);
}
Omit
Omit
konstruē tipu, izslēdzot rekvizītu kopu K
no T
, kur K
ir virknes literāļu tipu apvienojums, kas apzīmē rekvizītu nosaukumus, kurus vēlaties izslēgt. Tas ir pretējs Pick
.
Piemērs:
Izmantojot to pašu Event
interfeisu, ja vēlaties izveidot tipu jaunu pasākumu izveidei, iespējams, vēlēsities izslēgt rekvizītu id
, ko parasti ģenerē aizmugursistēma:
type NewEvent = Omit<Event, "id">;
function createEvent(event: NewEvent): void {
// ... ieviešana jauna pasākuma izveidei
}
Record
Record
konstruē objekta tipu, kura rekvizītu atslēgas ir K
un kura rekvizītu vērtības ir T
. K
var būt virknes literāļu tipu, skaitļu literāļu tipu vai simbola apvienojums. Tas ir lieliski piemērots vārdnīcu vai karšu izveidei.
Piemērs:
Iedomājieties, ka jums ir jāglabā tulkojumi jūsu lietojumprogrammas lietotāja interfeisam. Varat izmantot Record
, lai definētu tipu saviem tulkojumiem:
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; //Vienkāršots
return translations[key] || key; // Atgriezties pie atslēgas, ja tulkojums nav atrasts
}
console.log(translate("hello", "en")); // Izvade: Hello
console.log(translate("hello", "fr")); // Izvade: Bonjour
console.log(translate("nonexistent", "en")); // Izvade: nonexistent
Exclude
Exclude
konstruē tipu, izslēdzot no T
visus apvienojuma dalībniekus, kurus var piešķirt U
. Tas ir noderīgi, lai filtrētu noteiktus tipus no apvienojuma.
Piemērs:
Jums var būt tips, kas apzīmē dažādus pasākumu tipus:
type EventType = "concert" | "conference" | "workshop" | "webinar";
Ja vēlaties izveidot tipu, kas izslēdz "webinar" pasākumus, varat izmantot Exclude
:
type PhysicalEvent = Exclude<EventType, "webinar">;
// PhysicalEvent tagad ir "concert" | "conference" | "workshop"
function attendPhysicalEvent(event: PhysicalEvent): void {
console.log(`Apmeklē ${event}`);
}
// attendPhysicalEvent("webinar"); // Kļūda: Argumenta tips '"webinar"' nav piešķirams parametra tipam '"concert" | "conference" | "workshop"'.
attendPhysicalEvent("concert"); // Derīgs
Extract
Extract
konstruē tipu, izvelkot no T
visus apvienojuma dalībniekus, kurus var piešķirt U
. Tas ir pretējs Exclude
.
Piemērs:
Izmantojot to pašu EventType
, varat izvilkt vebināra pasākuma tipu:
type OnlineEvent = Extract<EventType, "webinar">;
// OnlineEvent tagad ir "webinar"
function attendOnlineEvent(event: OnlineEvent): void {
console.log(`Apmeklē ${event} tiešsaistē`);
}
attendOnlineEvent("webinar"); // Derīgs
// attendOnlineEvent("concert"); // Kļūda: Argumenta tips '"concert"' nav piešķirams parametra tipam '"webinar"'.
NonNullable
NonNullable
konstruē tipu, izslēdzot null
un undefined
no T
.
Piemērs:
type MaybeString = string | null | undefined;
type DefinitelyString = NonNullable<MaybeString>;
// DefinitelyString tagad ir string
function processString(str: DefinitelyString): void {
console.log(str.toUpperCase());
}
// processString(null); // Kļūda: Argumenta tips 'null' nav piešķirams parametra tipam 'string'.
// processString(undefined); // Kļūda: Argumenta tips 'undefined' nav piešķirams parametra tipam 'string'.
processString("hello"); // Derīgs
ReturnType
ReturnType
konstruē tipu, kas sastāv no funkcijas T
atgriešanas tipa.
Piemērs:
function greet(name: string): string {
return `Hello, ${name}!`;
}
type Greeting = ReturnType<typeof greet>;
// Greeting tagad ir string
const message: Greeting = greet("World");
console.log(message);
Parameters
Parameters
konstruē korteža tipu no funkcijas tipa T
parametru tipiem.
Piemērs:
function logEvent(eventName: string, eventData: object): void {
console.log(`Pasākums: ${eventName}`, eventData);
}
type LogEventParams = Parameters<typeof logEvent>;
// LogEventParams tagad ir [eventName: string, eventData: object]
const params: LogEventParams = ["user_login", { userId: "123", timestamp: Date.now() }];
logEvent(...params);
ConstructorParameters
ConstructorParameters
konstruē korteža vai masīva tipu no konstruktora funkcijas tipa T
parametru tipiem. Tas secina argumentu tipus, kas jānosūta klases konstruktoram.
Piemērs:
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}
type GreeterParams = ConstructorParameters<typeof Greeter>;
// GreeterParams tagad ir [message: string]
const paramsGreeter: GreeterParams = ["World"];
const greeterInstance = new Greeter(...paramsGreeter);
console.log(greeterInstance.greet()); // Izvades: Hello, World
Required
Required
konstruē tipu, kas sastāv no visiem T
rekvizītiem, kas iestatīti uz obligātiem. Tas padara visus neobligātos rekvizītus par obligātiem.
Piemērs:
interface UserProfile {
name: string;
age?: number;
email?: string;
}
type RequiredUserProfile = Required<UserProfile>;
// RequiredUserProfile tagad ir { name: string; age: number; email: string; }
const completeProfile: RequiredUserProfile = {
name: "Alice",
age: 30,
email: "alice@example.com"
};
// const incompleteProfile: RequiredUserProfile = { name: "Bob" }; // Kļūda: Īpašums 'age' trūkst tipā '{ name: string; }', bet tas ir nepieciešams tipā 'Required'.
Papildu utilītu tipi
Šablonu literāļu tipi
Šablonu literāļu tipi ļauj konstruēt jaunus virknes literāļu tipus, savienojot esošus virknes literāļu tipus, skaitļu literāļu tipus un citus. Tas nodrošina spēcīgu uz virkni balstītu tipu manipulāciju.
Piemērs:
type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE";
type APIEndpoint = `/api/users` | `/api/products`;
type RequestURL = `${HTTPMethod} ${APIEndpoint}`;
// RequestURL tagad ir "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(`Veic pieprasījumu uz ${url}`);
}
makeRequest("GET /api/users"); // Derīgs
// makeRequest("INVALID /api/users"); // Kļūda
Nosacījumu tipi
Nosacījumu tipi ļauj definēt tipus, kas ir atkarīgi no nosacījuma, kas izteikts kā tipa attiecība. Tie izmanto atslēgvārdu infer
, lai iegūtu informāciju par tipu.
Piemērs:
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
// Ja T ir Promise, tad tips ir U; pretējā gadījumā tips ir T.
async function fetchData(): Promise<number> {
return 42;
}
type Data = UnwrapPromise<ReturnType<typeof fetchData>>;
// Data tagad ir number
function processData(data: Data): void {
console.log(data * 2);
}
processData(await fetchData());
Praktiski pielietojumi un reālās pasaules scenāriji
Izpētīsim sarežģītākus reālās pasaules scenārijus, kur utilītu tipi spīd.
1. Veidlapu apstrāde
Strādājot ar veidlapām, bieži vien ir scenāriji, kad jāattēlo sākotnējās veidlapas vērtības, atjauninātās veidlapas vērtības un galīgās iesniegtās vērtības. Utilītu tipi var palīdzēt efektīvi pārvaldīt šos dažādos stāvokļus.
interface FormData {
firstName: string;
lastName: string;
email: string;
country: string; // Nepieciešams
city?: string; // Neobligāts
postalCode?: string;
newsletterSubscription?: boolean;
}
// Sākotnējās veidlapas vērtības (neobligāti lauki)
type InitialFormValues = Partial<FormData>;
// Atjauninātās veidlapas vērtības (daži lauki var trūkt)
type UpdatedFormValues = Partial<FormData>;
// Obligātie lauki iesniegšanai
type RequiredForSubmission = Required<Pick<FormData, 'firstName' | 'lastName' | 'email' | 'country'>>;
// Izmantojiet šos tipus savos veidlapu komponentos
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" }; // KĻŪDA: Trūkst 'country'
const submissionData: RequiredForSubmission = { firstName: "test", lastName: "test", email: "test", country: "USA" }; //OK
2. API datu transformācija
Patērējot datus no API, iespējams, dati ir jāpārveido citā formātā jūsu lietojumprogrammai. Utilītu tipi var palīdzēt definēt transformēto datu struktūru.
interface APIResponse {
user_id: string;
first_name: string;
last_name: string;
email_address: string;
profile_picture_url: string;
is_active: boolean;
}
// Pārveidojiet API atbildi lasāmākā formātā
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));
}
// Jūs pat varat ieviest tipu:
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. Konfigurācijas objektu apstrāde
Konfigurācijas objekti ir izplatīti daudzās lietojumprogrammās. Utilītu tipi var palīdzēt definēt konfigurācijas objekta struktūru un nodrošināt, ka tas tiek izmantots pareizi.
interface AppSettings {
theme: "light" | "dark";
language: string;
notificationsEnabled: boolean;
apiUrl?: string; // Neobligāts API URL dažādām vidēm
timeout?: number; //Neobligāts
}
// Noklusējuma iestatījumi
const defaultSettings: AppSettings = {
theme: "light",
language: "en",
notificationsEnabled: true
};
// Funkcija, lai apvienotu lietotāja iestatījumus ar noklusējuma iestatījumiem
function mergeSettings(userSettings: Partial<AppSettings>): AppSettings {
return { ...defaultSettings, ...userSettings };
}
// Izmantojiet apvienotos iestatījumus savā lietojumprogrammā
const mergedSettings = mergeSettings({ theme: "dark", apiUrl: "https://customapi.example.com" });
console.log(mergedSettings);
Padomi efektīvai utilītu tipu izmantošanai
- Sāciet vienkārši: Sāciet ar pamata utilītu tipiem, piemēram,
Partial
unReadonly
, pirms pāriet uz sarežģītākiem. - Izmantojiet aprakstošus nosaukumus: Piešķiriet saviem tipu aizstājvārdiem jēgpilnus nosaukumus, lai uzlabotu lasāmību.
- Apvienojiet utilītu tipus: Varat apvienot vairākus utilītu tipus, lai panāktu sarežģītas tipu transformācijas.
- Izmantojiet redaktora atbalstu: Izmantojiet TypeScript lielisko redaktora atbalstu, lai izpētītu utilītu tipu ietekmi.
- Izprotiet pamatjēdzienus: Stabila izpratne par TypeScript tipu sistēmu ir būtiska, lai efektīvi izmantotu utilītu tipus.
Secinājums
TypeScript utilītu tipi ir spēcīgi rīki, kas var ievērojami uzlabot jūsu koda kvalitāti un uzturamību. Izprotot un efektīvi piemērojot šos utilītu tipus, varat rakstīt tīrākas, tipdrošākas un stabilākas lietojumprogrammas, kas atbilst globālās izstrādes vides prasībām. Šajā rokasgrāmatā ir sniegts visaptverošs pārskats par izplatītākajiem utilītu tipiem un praktiskiem piemēriem. Eksperimentējiet ar tiem un izpētiet to potenciālu, lai uzlabotu savus TypeScript projektus. Atcerieties, ka, izmantojot utilītu tipus, prioritāte ir jāpiešķir lasāmībai un skaidrībai, un vienmēr jācenšas rakstīt kodu, ko ir viegli saprast un uzturēt, neatkarīgi no tā, kur atrodas jūsu kolēģi izstrādātāji.