Išlaisvinkite TypeScript pagalbinių tipų galią, kad rašytumėte švaresnį, lengviau prižiūrimą ir saugesnį kodą. Naršykite praktinius pritaikymus su realaus pasaulio pavyzdžiais kūrėjams visame pasaulyje.
TypeScript pagalbinių tipų įvaldymas: praktinis vadovas pasauliniams kūrėjams
TypeScript siūlo galingą įtaisytų pagalbinių tipų rinkinį, kuris gali žymiai padidinti jūsų kodo tipo saugumą, skaitomumą ir prižiūrimumą. Šie pagalbiniai tipai iš esmės yra iš anksto apibrėžtos tipo transformacijos, kurias galite pritaikyti esamiems tipams, taip išvengdami pasikartojančio ir klaidų linkusio kodo rašymo. Šiame vadove bus nagrinėjami įvairūs pagalbiniai tipai su praktiniais pavyzdžiais, kurie atitinka kūrėjų visame pasaulyje poreikius.
Kodėl naudoti pagalbinius tipus?
Pagalbiniai tipai sprendžia dažnus tipo manipuliavimo scenarijus. Pasinaudodami jais, galite:
- Sumažinti šabloninį kodą: Venkite rašyti pasikartojančius tipo apibrėžimus.
- Pagerinti tipo saugumą: Užtikrinkite, kad jūsų kodas atitiktų tipo apribojimus.
- Pagerinti kodo skaitomumą: Padarykite savo tipo apibrėžimus glaustesnius ir lengviau suprantamus.
- Padidinti prižiūrimumą: Supaprastinkite modifikacijas ir sumažinkite klaidų įvedimo riziką.
Pagrindiniai pagalbiniai tipai
Partial
Partial
sukuria tipą, kuriame visos T
savybės yra nustatytos kaip pasirenkamos. Tai ypač naudinga, kai norite sukurti tipą daliniams atnaujinimams arba konfigūracijos objektams.
Pavyzdys:
Įsivaizduokite, kad kuriate elektroninės prekybos platformą su klientais iš įvairių regionų. Jūs turite Customer
tipą:
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;
}
}
Atnaujindami kliento informaciją, galbūt nenorėsite reikalauti visų laukų. Partial
leidžia apibrėžti tipą, kuriame visos Customer
savybės yra pasirenkamos:
type PartialCustomer = Partial<Customer>;
function updateCustomer(id: string, updates: PartialCustomer): void {
// ... įgyvendinimas kliento atnaujinimui su nurodytu ID
}
updateCustomer("123", { firstName: "John", lastName: "Doe" }); // Galioja
updateCustomer("456", { address: { city: "London" } }); // Galioja
Readonly
Readonly
sukuria tipą, kuriame visos T
savybės yra nustatytos kaip readonly
, užkertant kelią modifikavimui po inicializavimo. Tai yra vertinga užtikrinant nekeičiamumą.
Pavyzdys:
Apsvarstykite konfigūracijos objektą savo pasaulinei programai:
interface AppConfig {
apiUrl: string;
theme: string;
supportedLanguages: string[];
version: string; // Pridėta versija
}
const config: AppConfig = {
apiUrl: "https://api.example.com",
theme: "dark",
supportedLanguages: ["en", "fr", "de", "es", "zh"],
version: "1.0.0"
};
Norėdami išvengti atsitiktinio konfigūracijos modifikavimo po inicializavimo, galite naudoti 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"; // Klaida: Negalima priskirti 'apiUrl', nes tai yra tik skaitymui skirta savybė.
Pick
Pick
sukuria tipą, parinkdamas savybių rinkinį K
iš T
, kur K
yra eilutinių literalų tipų sąjunga, atstovaujanti savybių pavadinimus, kuriuos norite įtraukti.
Pavyzdys:
Tarkime, kad turite Event
sąsają su įvairiomis savybėmis:
interface Event {
id: string;
title: string;
description: string;
location: string;
startTime: Date;
endTime: Date;
organizer: string;
attendees: string[];
}
Jei jums reikia tik title
, location
ir startTime
konkrečiam rodymo komponentui, galite naudoti Pick
:
type EventSummary = Pick<Event, "title" | "location" | "startTime">;
function displayEventSummary(event: EventSummary): void {
console.log(`Įvykis: ${event.title} at ${event.location} on ${event.startTime}`);
}
Omit
Omit
sukuria tipą, išskirdamas savybių rinkinį K
iš T
, kur K
yra eilutinių literalų tipų sąjunga, atstovaujanti savybių pavadinimus, kuriuos norite išskirti. Tai yra Pick
priešingybė.
Pavyzdys:
Naudojant tą pačią Event
sąsają, jei norite sukurti tipą naujiems įvykiams kurti, galbūt norėsite išskirti id
savybę, kuri paprastai generuojama backend'e:
type NewEvent = Omit<Event, "id">;
function createEvent(event: NewEvent): void {
// ... įgyvendinimas naujo įvykio kūrimui
}
Record
Record
sukuria objekto tipą, kurio savybių raktai yra K
, o savybių reikšmės yra T
. K
gali būti eilutinių literalų tipų, skaičių literalų tipų arba simbolių sąjunga. Tai puikiai tinka žodynų ar žemėlapių kūrimui.
Pavyzdys:
Įsivaizduokite, kad jums reikia saugoti savo programos vartotojo sąsajos vertimus. Galite naudoti Record
, kad apibrėžtumėte savo vertimų tipą:
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; //Supaprastinta
return translations[key] || key; // Atsarginis variantas į raktą, jei vertimas nerastas
}
console.log(translate("hello", "en")); // Išvestis: Hello
console.log(translate("hello", "fr")); // Išvestis: Bonjour
console.log(translate("nonexistent", "en")); // Išvestis: nonexistent
Exclude
Exclude
sukuria tipą, išskirdamas iš T
visus sąjungos narius, kurie gali būti priskirti U
. Tai naudinga filtruojant konkrečius tipus iš sąjungos.
Pavyzdys:
Galite turėti tipą, atstovaujantį skirtingus įvykių tipus:
type EventType = "concert" | "conference" | "workshop" | "webinar";
Jei norite sukurti tipą, kuris išskiria „webinar“ įvykius, galite naudoti Exclude
:
type PhysicalEvent = Exclude<EventType, "webinar">;
// PhysicalEvent dabar yra "concert" | "conference" | "workshop"
function attendPhysicalEvent(event: PhysicalEvent): void {
console.log(`Dalyvauju ${event}`);
}
// attendPhysicalEvent("webinar"); // Klaida: argumento tipas '"webinar"' negali būti priskirtas parametrui, kurio tipas yra '"concert" | "conference" | "workshop"'.
attendPhysicalEvent("concert"); // Galioja
Extract
Extract
sukuria tipą, ištraukdamas iš T
visus sąjungos narius, kurie gali būti priskirti U
. Tai yra Exclude
priešingybė.
Pavyzdys:
Naudojant tą patį EventType
, galite ištraukti webinar įvykio tipą:
type OnlineEvent = Extract<EventType, "webinar">;
// OnlineEvent dabar yra "webinar"
function attendOnlineEvent(event: OnlineEvent): void {
console.log(`Dalyvauju ${event} internetu`);
}
attendOnlineEvent("webinar"); // Galioja
// attendOnlineEvent("concert"); // Klaida: argumento tipas '"concert"' negali būti priskirtas parametrui, kurio tipas yra '"webinar"'.
NonNullable
NonNullable
sukuria tipą, išskirdamas null
ir undefined
iš T
.
Pavyzdys:
type MaybeString = string | null | undefined;
type DefinitelyString = NonNullable<MaybeString>;
// DefinitelyString dabar yra string
function processString(str: DefinitelyString): void {
console.log(str.toUpperCase());
}
// processString(null); // Klaida: argumento tipas 'null' negali būti priskirtas parametrui, kurio tipas yra 'string'.
// processString(undefined); // Klaida: argumento tipas 'undefined' negali būti priskirtas parametrui, kurio tipas yra 'string'.
processString("hello"); // Galioja
ReturnType
ReturnType
sukuria tipą, kurį sudaro funkcijos T
grąžinamas tipas.
Pavyzdys:
function greet(name: string): string {
return `Hello, ${name}!`;
}
type Greeting = ReturnType<typeof greet>;
// Greeting dabar yra string
const message: Greeting = greet("World");
console.log(message);
Parameters
Parameters
sukuria rinkinio tipą iš funkcijos tipo T
parametrų tipų.
Pavyzdys:
function logEvent(eventName: string, eventData: object): void {
console.log(`Įvykis: ${eventName}`, eventData);
}
type LogEventParams = Parameters<typeof logEvent>;
// LogEventParams dabar yra [eventName: string, eventData: object]
const params: LogEventParams = ["user_login", { userId: "123", timestamp: Date.now() }];
logEvent(...params);
ConstructorParameters
ConstructorParameters
sukuria rinkinio arba masyvo tipą iš konstruktoriaus funkcijos tipo T
parametrų tipų. Jis nustato argumentų, kuriuos reikia perduoti klasės konstruktoriui, tipus.
Pavyzdys:
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}
type GreeterParams = ConstructorParameters<typeof Greeter>;
// GreeterParams dabar yra [message: string]
const paramsGreeter: GreeterParams = ["World"];
const greeterInstance = new Greeter(...paramsGreeter);
console.log(greeterInstance.greet()); // Išvestis: Hello, World
Required
Required
sukuria tipą, kurį sudaro visos T
savybės, nustatytos kaip privalomos. Tai padaro visas pasirenkamas savybes privalomomis.
Pavyzdys:
interface UserProfile {
name: string;
age?: number;
email?: string;
}
type RequiredUserProfile = Required<UserProfile>;
// RequiredUserProfile dabar yra { name: string; age: number; email: string; }
const completeProfile: RequiredUserProfile = {
name: "Alice",
age: 30,
email: "alice@example.com"
};
// const incompleteProfile: RequiredUserProfile = { name: "Bob" }; // Klaida: Savybė 'age' trūksta tipe '{ name: string; }', bet yra privaloma tipe 'Required'.
Išplėstiniai pagalbiniai tipai
Šablonų literalų tipai
Šablonų literalų tipai leidžia kurti naujus eilutinių literalų tipus, sujungiant esamus eilutinių literalų tipus, skaičių literalų tipus ir dar daugiau. Tai leidžia galingą eilutėmis pagrįstą tipo manipuliavimą.
Pavyzdys:
type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE";
type APIEndpoint = `/api/users` | `/api/products`;
type RequestURL = `${HTTPMethod} ${APIEndpoint}`;
// RequestURL dabar yra "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(`Vykdomas užklausimas į ${url}`);
}
makeRequest("GET /api/users"); // Galioja
// makeRequest("INVALID /api/users"); // Klaida
Sąlyginiai tipai
Sąlyginiai tipai leidžia apibrėžti tipus, kurie priklauso nuo sąlygos, išreikštos kaip tipo ryšys. Jie naudoja infer
raktinį žodį, kad ištrauktų tipo informaciją.
Pavyzdys:
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
// Jei T yra Promise, tada tipas yra U; kitu atveju tipas yra T.
async function fetchData(): Promise<number> {
return 42;
}
type Data = UnwrapPromise<ReturnType<typeof fetchData>>;
// Data dabar yra number
function processData(data: Data): void {
console.log(data * 2);
}
processData(await fetchData());
Praktinis pritaikymas ir realaus pasaulio scenarijai
Panagrinėkime sudėtingesnius realaus pasaulio scenarijus, kuriuose pagalbiniai tipai spindi.
1. Formų apdorojimas
Dirbdami su formomis, dažnai turite scenarijų, kai reikia atspindėti pradinės formos reikšmes, atnaujintas formos reikšmes ir galutines pateiktas reikšmes. Pagalbiniai tipai gali padėti efektyviai valdyti šias skirtingas būsenas.
interface FormData {
firstName: string;
lastName: string;
email: string;
country: string; // Privaloma
city?: string; // Pasirenkama
postalCode?: string;
newsletterSubscription?: boolean;
}
// Pradinės formos reikšmės (pasirenkami laukai)
type InitialFormValues = Partial<FormData>;
// Atnaujintos formos reikšmės (kai kurių laukų gali trūkti)
type UpdatedFormValues = Partial<FormData>;
// Privalomi laukai pateikimui
type RequiredForSubmission = Required<Pick<FormData, 'firstName' | 'lastName' | 'email' | 'country'>>;
// Naudokite šiuos tipus savo formos komponentuose
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" }; // KLAIDA: Trūksta 'country'
const submissionData: RequiredForSubmission = { firstName: "test", lastName: "test", email: "test", country: "USA" }; //GERAI
2. API duomenų transformavimas
Naudodami duomenis iš API, galbūt norėsite transformuoti duomenis į kitokį formatą savo programai. Pagalbiniai tipai gali padėti apibrėžti transformuotų duomenų struktūrą.
interface APIResponse {
user_id: string;
first_name: string;
last_name: string;
email_address: string;
profile_picture_url: string;
is_active: boolean;
}
// Transformuokite API atsakymą į labiau įskaitomą formatą
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 netgi galite primesti tipą:
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. Konfigūracijos objektų apdorojimas
Konfigūracijos objektai yra dažni daugelyje programų. Pagalbiniai tipai gali padėti apibrėžti konfigūracijos objekto struktūrą ir užtikrinti, kad jis būtų naudojamas teisingai.
interface AppSettings {
theme: "light" | "dark";
language: string;
notificationsEnabled: boolean;
apiUrl?: string; // Pasirenkamas API URL skirtingoms aplinkoms
timeout?: number; //Pasirenkama
}
// Numatytieji nustatymai
const defaultSettings: AppSettings = {
theme: "light",
language: "en",
notificationsEnabled: true
};
// Funkcija sujungti vartotojo nustatymus su numatytaisiais nustatymais
function mergeSettings(userSettings: Partial<AppSettings>): AppSettings {
return { ...defaultSettings, ...userSettings };
}
// Naudokite sujungtus nustatymus savo programoje
const mergedSettings = mergeSettings({ theme: "dark", apiUrl: "https://customapi.example.com" });
console.log(mergedSettings);
Patarimai, kaip efektyviai naudoti pagalbinius tipus
- Pradėkite nuo paprasto: Pradėkite nuo pagrindinių pagalbinių tipų, tokių kaip
Partial
irReadonly
, prieš pereidami prie sudėtingesnių. - Naudokite aprašomuosius pavadinimus: Suteikite savo tipo pseudonimams prasmingus pavadinimus, kad pagerintumėte skaitomumą.
- Sujunkite pagalbinius tipus: Galite sujungti kelis pagalbinius tipus, kad pasiektumėte sudėtingas tipo transformacijas.
- Pasinaudokite redaktoriaus palaikymu: Pasinaudokite puikiu TypeScript redaktoriaus palaikymu, kad ištirtumėte pagalbinių tipų poveikį.
- Supraskite pagrindines sąvokas: Tvirtas TypeScript tipo sistemos supratimas yra būtinas efektyviam pagalbinių tipų naudojimui.
Išvada
TypeScript pagalbiniai tipai yra galingi įrankiai, kurie gali žymiai pagerinti jūsų kodo kokybę ir prižiūrimumą. Suprasdami ir efektyviai taikydami šiuos pagalbinius tipus, galite rašyti švaresnes, saugesnes ir patikimesnes programas, kurios atitinka pasaulinės kūrimo aplinkos poreikius. Šiame vadove pateikiama išsami bendrų pagalbinių tipų apžvalga ir praktiniai pavyzdžiai. Eksperimentuokite su jais ir ištirkite jų potencialą pagerinti savo TypeScript projektus. Atminkite, kad naudodami pagalbinius tipus, pirmenybę teikite skaitomumui ir aiškumui, ir visada stenkitės rašyti kodą, kurį būtų lengva suprasti ir prižiūrėti, nepaisant to, kur yra jūsų kolegos kūrėjai.