Lietuvių

Išsamus TypeScript indeksų signatūrų vadovas, leidžiantis dinamiškai pasiekti savybes, užtikrinti tipų saugumą ir lanksčias duomenų struktūras tarptautinei programinės įrangos kūrimui.

TypeScript Index Signatures: Mastering Dynamic Property Access

Programinės įrangos kūrimo pasaulyje lankstumas ir tipų saugumas dažnai suvokiami kaip priešingos jėgos. TypeScript, JavaScript aibės poaibis, elegantiškai sumažina šį atotrūkį, siūlydamas funkcijas, kurios pagerina abu. Viena tokia galinga funkcija yra indeksų signatūros. Šis išsamus vadovas gilinasi į TypeScript indeksų signatūrų subtilybes, paaiškindamas, kaip jos įgalina dinamišką savybių priėjimą išlaikant tvirtą tipų tikrinimą. Tai ypač svarbu programoms, kurios sąveikauja su duomenimis iš įvairių šaltinių ir formatų visame pasaulyje.

What are TypeScript Index Signatures?

Indeksų signatūros suteikia būdą apibūdinti objekto savybių tipus, kai iš anksto nežinote savybių pavadinimų arba kai savybių pavadinimai nustatomi dinamiškai. Pagalvokite apie juos kaip apie būdą pasakyti: "Šis objektas gali turėti bet kokį skaičių šio konkretaus tipo savybių." Jos deklaruojamos sąsajoje arba tipo slapyvardyje naudojant šią sintaksę:


interface MyInterface {
  [index: string]: number;
}

Šiame pavyzdyje [index: string]: number yra indeksų signatūra. Išskaidykime komponentus:

Todėl MyInterface apibūdina objektą, kuriame bet kuri eilutės savybė (pvz., "age", "count", "user123") turi turėti skaičiaus vertę. Tai leidžia lankstumą dirbant su duomenimis, kai tikslūs raktai nežinomi iš anksto, o tai dažnai pasitaiko scenarijuose, susijusiuose su išoriniais API arba vartotojų sukurtu turiniu.

Why Use Index Signatures?

Indeksų signatūros yra neįkainojamos įvairiuose scenarijuose. Štai keletas pagrindinių privalumų:

Index Signatures in Action: Practical Examples

Panagrinėkime keletą praktinių pavyzdžių, iliustruojančių indeksų signatūrų galią.

Example 1: Representing a Dictionary of Strings

Įsivaizduokite, kad jums reikia pavaizduoti žodyną, kuriame raktai yra šalių kodai (pvz., "US", "CA", "GB"), o vertės yra šalių pavadinimai. Galite naudoti indeksų signatūrą tipo apibrėžimui:


interface CountryDictionary {
  [code: string]: string; // Raktas yra šalies kodas (eilutė), vertė yra šalies pavadinimas (eilutė)
}

const countries: CountryDictionary = {
  "US": "United States",
  "CA": "Canada",
  "GB": "United Kingdom",
  "DE": "Germany"
};

console.log(countries["US"]); // Išvestis: United States

// Klaida: Type 'number' is not assignable to type 'string'.
// countries["FR"] = 123; 

Šis pavyzdys parodo, kaip indeksų signatūra užtikrina, kad visos vertės turi būti eilutės. Bandymas priskirti skaičių šalies kodui sukels tipo klaidą.

Example 2: Handling API Responses

Įsivaizduokite API, kuri grąžina vartotojo profilius. API gali apimti pasirinktinius laukus, kurie skiriasi nuo vartotojo iki vartotojo. Galite naudoti indeksų signatūrą, kad pavaizduotumėte šiuos pasirinktinius laukus:


interface UserProfile {
  id: number;
  name: string;
  email: string;
  [key: string]: any; // Leisti bet kurią kitą eilutės savybę su bet kokiu tipu
}

const user: UserProfile = {
  id: 123,
  name: "Alice",
  email: "alice@example.com",
  customField1: "Value 1",
  customField2: 42,
};

console.log(user.name); // Išvestis: Alice
console.log(user.customField1); // Išvestis: Value 1

Šiuo atveju [key: string]: any indeksų signatūra leidžia UserProfile sąsajai turėti bet kokį skaičių papildomų eilutės savybių su bet kokiu tipu. Tai suteikia lankstumo, kartu užtikrinant, kad id, name ir email savybės būtų teisingai įvestos. Tačiau `any` naudojimas turėtų būti vertinamas atsargiai, nes jis sumažina tipų saugumą. Apsvarstykite galimybę naudoti konkretesnį tipą, jei įmanoma.

Example 3: Validating Dynamic Configuration

Tarkime, kad turite konfigūracijos objektą, įkeltą iš išorinio šaltinio. Galite naudoti indeksų signatūras, kad patvirtintumėte, jog konfigūracijos vertės atitinka numatomus tipus:


interface Config {
  [key: string]: string | number | boolean;
}

const config: Config = {
  apiUrl: "https://api.example.com",
  timeout: 5000,
  debugMode: true,
};

function validateConfig(config: Config): void {
  if (typeof config.timeout !== 'number') {
    console.error("Invalid timeout value");
  }
  // More validation...
}

validateConfig(config);

Čia indeksų signatūra leidžia konfigūracijos vertėms būti eilutėmis, skaičiais arba loginėmis vertėmis. Tada validateConfig funkcija gali atlikti papildomus patikrinimus, siekiant užtikrinti, kad vertės būtų tinkamos numatomam naudojimui.

String vs. Number Index Signatures

Kaip minėta anksčiau, TypeScript palaiko tiek string, tiek number indeksų signatūras. Suprasti skirtumus yra labai svarbu norint jas efektyviai naudoti.

String Index Signatures

Eilutės indeksų signatūros leidžia pasiekti savybes naudojant eilutės raktus. Tai yra labiausiai paplitęs indeksų signatūros tipas ir yra tinkamas objektams, kurių savybių pavadinimai yra eilutės, vaizduoti.


interface StringDictionary {
  [key: string]: any;
}

const data: StringDictionary = {
  name: "John",
  age: 30,
  city: "New York"
};

console.log(data["name"]); // Išvestis: John

Number Index Signatures

Skaičiaus indeksų signatūros leidžia pasiekti savybes naudojant skaičių raktus. Tai paprastai naudojama masyvams arba į masyvą panašiems objektams vaizduoti. TypeScript, jei apibrėžiate skaičiaus indeksų signatūrą, skaitinio indeksuotojo tipas turi būti eilutės indeksuotojo tipo potipis.


interface NumberArray {
  [index: number]: string;
}

const myArray: NumberArray = [
  "apple",
  "banana",
  "cherry"
];

console.log(myArray[0]); // Išvestis: apple

Important Note: Naudojant skaičiaus indeksų signatūras, TypeScript automatiškai konvertuos skaičius į eilutes, kai bus pasiekiamos savybės. Tai reiškia, kad myArray[0] yra lygiavertis myArray["0"].

Advanced Index Signature Techniques

Be pagrindų, galite pasinaudoti indeksų signatūromis su kitomis TypeScript funkcijomis, kad sukurtumėte dar galingesnius ir lankstesnius tipų apibrėžimus.

Combining Index Signatures with Specific Properties

Galite sujungti indeksų signatūras su aiškiai apibrėžtomis savybėmis sąsajoje arba tipo slapyvardyje. Tai leidžia apibrėžti reikiamas savybes kartu su dinamiškai pridedamomis savybėmis.


interface Product {
  id: number;
  name: string;
  price: number;
  [key: string]: any; // Leisti papildomas bet kokio tipo savybes
}

const product: Product = {
  id: 123,
  name: "Laptop",
  price: 999.99,
  description: "High-performance laptop",
  warranty: "2 years"
};

Šiame pavyzdyje Product sąsaja reikalauja id, name ir price savybių, taip pat leidžia papildomas savybes per indeksų signatūrą.

Using Generics with Index Signatures

Generiniai tipai suteikia būdą sukurti pakartotinai naudojamus tipų apibrėžimus, kurie gali veikti su skirtingais tipais. Galite naudoti generinius tipus su indeksų signatūromis, kad sukurtumėte generines duomenų struktūras.


interface Dictionary {
  [key: string]: T;
}

const stringDictionary: Dictionary = {
  name: "John",
  city: "New York"
};

const numberDictionary: Dictionary = {
  age: 30,
  count: 100
};

Čia Dictionary sąsaja yra generinis tipo apibrėžimas, leidžiantis sukurti žodynus su skirtingais verčių tipais. Tai leidžia išvengti to paties indeksų signatūros apibrėžimo kartojimo įvairiems duomenų tipams.

Index Signatures with Union Types

Galite naudoti sąjungos tipus su indeksų signatūromis, kad savybės galėtų turėti skirtingus tipus. Tai naudinga dirbant su duomenimis, kurie gali turėti kelis galimus tipus.


interface MixedData {
  [key: string]: string | number | boolean;
}

const mixedData: MixedData = {
  name: "John",
  age: 30,
  isActive: true
};

Šiame pavyzdyje MixedData sąsaja leidžia savybėms būti eilutėmis, skaičiais arba loginėmis vertėmis.

Index Signatures with Literal Types

Galite naudoti literal tipus, kad apribotumėte galimas indekso vertes. Tai gali būti naudinga, kai norite įgyvendinti konkretų leidžiamų savybių pavadinimų rinkinį.


type AllowedKeys = "name" | "age" | "city";

interface RestrictedData {
  [key in AllowedKeys]: string | number;
}

const restrictedData: RestrictedData = {
  name: "John",
  age: 30,
  city: "New York"
};

Šis pavyzdys naudoja literal tipą AllowedKeys, kad apribotų savybių pavadinimus iki "name", "age" ir "city". Tai suteikia griežtesnį tipų tikrinimą, palyginti su generine `string` indekso signatūra.

Using the `Record` Utility Type

TypeScript suteikia įtaisytąjį pagalbinį tipą, vadinamą `Record`, kuris iš esmės yra trumpinys apibrėžiant indeksų signatūrą su konkrečiu rakto tipu ir vertės tipu.


// Equivalent to: { [key: string]: number }
const recordExample: Record = {
  a: 1,
  b: 2,
  c: 3
};

// Equivalent to: { [key in 'x' | 'y']: boolean }
const xyExample: Record<'x' | 'y', boolean> = {
  x: true,
  y: false
};

`Record` tipas supaprastina sintaksę ir pagerina skaitomumą, kai jums reikia paprastos į žodyną panašios struktūros.

Using Mapped Types with Index Signatures

Mapped tipai leidžia transformuoti esamo tipo savybes. Jie gali būti naudojami kartu su indeksų signatūromis, kad sukurtumėte naujus tipus, pagrįstus esamais tipais.


interface Person {
  name: string;
  age: number;
  email?: string; // Pasirenkama savybė
}

// Make all properties of Person required
type RequiredPerson = { [K in keyof Person]-?: Person[K] };

const requiredPerson: RequiredPerson = {
  name: "Alice",
  age: 30,   // Email is now required.
  email: "alice@example.com" 
};

Šiame pavyzdyje RequiredPerson tipas naudoja mapped tipą su indeksų signatūra, kad visos Person sąsajos savybės taptų privalomos. `-?` pašalina pasirenkamą modifikatorių iš el. pašto savybės.

Best Practices for Using Index Signatures

Nors indeksų signatūros siūlo didelį lankstumą, svarbu jas naudoti apgalvotai, kad būtų išlaikytas tipų saugumas ir kodo aiškumas. Štai keletas geriausių praktikų:

Common Pitfalls and How to Avoid Them

Net ir gerai suprantant indeksų signatūras, lengva pakliūti į kai kuriuos dažnus spąstus. Štai į ką reikia atkreipti dėmesį:

Internationalization and Localization Considerations

Kuriant programinę įrangą pasaulinei auditorijai, labai svarbu atsižvelgti į internacionalizavimą (i18n) ir lokalizavimą (l10n). Indeksų signatūros gali atlikti svarbų vaidmenį tvarkant lokalizuotus duomenis.

Example: Localized Text

Galite naudoti indeksų signatūras, kad pavaizduotumėte lokalizuotų teksto eilučių rinkinį, kur raktai yra kalbos kodai (pvz., "en", "fr", "de"), o vertės yra atitinkamos teksto eilutės.


interface LocalizedText {
  [languageCode: string]: string;
}

const localizedGreeting: LocalizedText = {
  "en": "Hello",
  "fr": "Bonjour",
  "de": "Hallo"
};

function getGreeting(languageCode: string): string {
  return localizedGreeting[languageCode] || "Hello"; // Numatytoji reikšmė yra anglų kalba, jei nerasta
}

console.log(getGreeting("fr")); // Išvestis: Bonjour
console.log(getGreeting("es")); // Išvestis: Hello (numatytoji)

Šis pavyzdys parodo, kaip indeksų signatūros gali būti naudojamos saugoti ir atgauti lokalizuotą tekstą pagal kalbos kodą. Numatytoji reikšmė pateikiama, jei prašoma kalba nerasta.

Conclusion

TypeScript indeksų signatūros yra galingas įrankis dirbant su dinamiškais duomenimis ir kuriant lanksčius tipų apibrėžimus. Suprasdami šioje gairėje išdėstytas sąvokas ir geriausią praktiką, galite pasinaudoti indeksų signatūromis, kad pagerintumėte TypeScript kodo tipų saugumą ir pritaikomumą. Atminkite, kad jas naudotumėte apgalvotai, teikdami pirmenybę specifiškumui ir aiškumui, kad išlaikytumėte kodo kokybę. Tęsdami savo TypeScript kelionę, indeksų signatūrų tyrinėjimas neabejotinai atvers naujų galimybių kuriant patikimas ir keičiamo dydžio programas pasaulinei auditorijai. Įvaldę indeksų signatūras, galite rašyti išraiškingesnį, lengviau prižiūrimą ir tipų saugų kodą, todėl jūsų projektai taps patikimesni ir labiau pritaikomi prie įvairių duomenų šaltinių ir besikeičiančių reikalavimų. Pasinaudokite TypeScript ir jos indeksų signatūrų galia, kad kartu kurtumėte geresnę programinę įrangą.

TypeScript indeksų signatūros: dinamiško savybių priėjimo įvaldymas | MLOG