Latviešu

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:

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 un Readonly, 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.