Išmokite, kaip panaudoti „TypeScript“ susietuosius tipus dinamiškai transformuoti objektų formas, sukuriant tvirtą ir lengvai prižiūrimą kodą globalioms programoms.
TypeScript susietieji tipai (Mapped Types) dinamiškoms objektų transformacijoms: išsamus vadovas
„TypeScript“, pabrėžiantis statinį tipizavimą, suteikia programuotojams galimybę rašyti patikimesnį ir lengviau prižiūrimą kodą. Ypač svarbi funkcija, kuri prie to ženkliai prisideda, yra susietieji tipai (angl. mapped types). Šiame vadove gilinamasi į „TypeScript“ susietųjų tipų pasaulį, pateikiant išsamų jų funkcionalumo, privalumų ir praktinio pritaikymo supratimą, ypač kuriant globalius programinės įrangos sprendimus.
Pagrindinių koncepcijų supratimas
Iš esmės, susietasis tipas leidžia sukurti naują tipą, remiantis esamo tipo savybėmis. Jūs apibrėžiate naują tipą iteruodami per kito tipo raktus ir taikydami transformacijas reikšmėms. Tai nepaprastai naudinga scenarijuose, kai reikia dinamiškai keisti objektų struktūrą, pavyzdžiui, keisti savybių duomenų tipus, padaryti savybes neprivalomas arba pridėti naujų savybių, pagrįstų esamomis.
Pradėkime nuo pagrindų. Apsvarstykime paprastą sąsają:
interface Person {
name: string;
age: number;
email: string;
}
Dabar apibrėžkime susietąjį tipą, kuris visas Person
savybes padaro neprivalomas:
type OptionalPerson = {
[K in keyof Person]?: Person[K];
};
Šiame pavyzdyje:
[K in keyof Person]
iteruoja per kiekvienąPerson
sąsajos raktą (name
,age
,email
).?
kiekvieną savybę padaro neprivaloma.Person[K]
nurodo savybės tipą originaliojePerson
sąsajoje.
Gautas OptionalPerson
tipas iš esmės atrodo taip:
{
name?: string;
age?: number;
email?: string;
}
Tai parodo susietųjų tipų galią dinamiškai modifikuoti esamus tipus.
Susietųjų tipų sintaksė ir struktūra
Susietojo tipo sintaksė yra gana specifinė ir laikosi šios bendros struktūros:
type NewType = {
[Key in KeysType]: ValueType;
};
Išnagrinėkime kiekvieną komponentą:
NewType
: Pavadinimas, kurį priskiriate kuriamam naujam tipui.[Key in KeysType]
: Tai yra susietojo tipo esmė.Key
yra kintamasis, kuris iteruoja per kiekvienąKeysType
narį.KeysType
dažnai, bet не visada, yrakeyof
kito tipo (kaip mūsųOptionalPerson
pavyzdyje). Tai taip pat gali būti eilutės literalų junginys (union) arba sudėtingesnis tipas.ValueType
: Tai nurodo savybės tipą naujame tipe. Tai gali būti tiesioginis tipas (pvz.,string
), tipas, pagrįstas originalaus tipo savybe (pvz.,Person[K]
), arba sudėtingesnė originalaus tipo transformacija.
Pavyzdys: Savybių tipų transformavimas
Įsivaizduokite, kad reikia konvertuoti visas skaitines objekto savybes į eilutes. Štai kaip tai galėtumėte padaryti naudodami susietąjį tipą:
interface Product {
id: number;
name: string;
price: number;
quantity: number;
}
type StringifiedProduct = {
[K in keyof Product]: Product[K] extends number ? string : Product[K];
};
Šiuo atveju mes:
- Iteruojame per kiekvieną
Product
sąsajos raktą. - Naudojame sąlyginį tipą (
Product[K] extends number ? string : Product[K]
), kad patikrintume, ar savybė yra skaičius. - Jei tai skaičius, savybės tipą nustatome kaip
string
; kitu atveju paliekame originalų tipą.
Gautas StringifiedProduct
tipas būtų:
{
id: string;
name: string;
price: string;
quantity: string;
}
Pagrindinės funkcijos ir metodai
1. keyof
ir indeksų signatūrų naudojimas
Kaip parodyta anksčiau, keyof
yra pagrindinis įrankis dirbant su susietaisiais tipais. Jis leidžia iteruoti per tipo raktus. Indeksų signatūros suteikia būdą apibrėžti savybių tipą, kai iš anksto nežinote raktų, bet vis tiek norite juos transformuoti.
Pavyzdys: Visų savybių transformavimas pagal indekso signatūrą
interface StringMap {
[key: string]: number;
}
type StringMapToString = {
[K in keyof StringMap]: string;
};
Čia visos skaitinės reikšmės „StringMap“ yra konvertuojamos į eilutes naujame tipe.
2. Sąlyginiai tipai susietuosiuose tipuose
Sąlyginiai tipai yra galinga „TypeScript“ funkcija, leidžianti išreikšti tipų ryšius, pagrįstus sąlygomis. Derinant su susietaisiais tipais, jie leidžia atlikti labai sudėtingas transformacijas.
Pavyzdys: `null` ir `undefined` pašalinimas iš tipo
type NonNullableProperties = {
[K in keyof T]: T[K] extends (null | undefined) ? never : T[K];
};
Šis susietasis tipas iteruoja per visus tipo T
raktus ir naudoja sąlyginį tipą, kad patikrintų, ar reikšmė leidžia `null` arba `undefined`. Jei taip, tipas tampa `never`, efektyviai pašalinant tą savybę; kitu atveju, jis išlaiko pradinį tipą. Šis metodas daro tipus tvirtesnius, pašalindamas potencialiai problemiškas `null` ar `undefined` reikšmes, gerindamas kodo kokybę ir atitikdamas geriausias globalios programinės įrangos kūrimo praktikas.
3. Pagalbiniai tipai efektyvumui
„TypeScript“ teikia integruotus pagalbinius tipus, kurie supaprastina įprastas tipų manipuliavimo užduotis. Šie tipai užkulisiuose naudoja susietuosius tipus.
Partial
: Padaro visas tipoT
savybes neprivalomas (kaip parodyta ankstesniame pavyzdyje).Required
: Padaro visas tipoT
savybes privalomas.Readonly
: Padaro visas tipoT
savybes tik skaitomas.Pick
: Sukuria naują tipą tik su nurodytais raktais (K
) iš tipoT
.Omit
: Sukuria naują tipą su visomis tipoT
savybėmis, išskyrus nurodytus raktus (K
).
Pavyzdys: Pick
ir Omit
naudojimas
interface User {
id: number;
name: string;
email: string;
role: string;
}
type UserSummary = Pick;
// { id: number; name: string; }
type UserWithoutEmail = Omit;
// { id: number; name: string; role: string; }
Šie pagalbiniai tipai sutaupo jums nuo pasikartojančių susietųjų tipų apibrėžimų rašymo ir pagerina kodo skaitomumą. Jie ypač naudingi globaliame programavime, valdant skirtingus duomenų vaizdus ar prieigos lygius, atsižvelgiant į vartotojo teises ar programos kontekstą.
Pritaikymas ir pavyzdžiai realiame pasaulyje
1. Duomenų patvirtinimas ir transformavimas
Susietieji tipai yra neįkainojami patvirtinant ir transformuojant duomenis, gautus iš išorinių šaltinių (API, duomenų bazių, vartotojo įvesties). Tai labai svarbu globaliose programose, kur gali tekti dirbti su duomenimis iš daugybės skirtingų šaltinių ir reikia užtikrinti duomenų vientisumą. Jie leidžia apibrėžti konkrečias taisykles, tokias kaip duomenų tipo patvirtinimas, ir automatiškai modifikuoti duomenų struktūras pagal šias taisykles.
Pavyzdys: API atsakymo konvertavimas
interface ApiResponse {
userId: string;
id: string;
title: string;
completed: boolean;
}
type CleanedApiResponse = {
[K in keyof ApiResponse]:
K extends 'userId' | 'id' ? number :
K extends 'title' ? string :
K extends 'completed' ? boolean : any;
};
Šis pavyzdys transformuoja userId
ir id
savybes (kurios iš API gaunamos kaip eilutės) į skaičius. title
savybė teisingai tipizuojama kaip eilutė, o completed
lieka loginio tipo (boolean). Tai užtikrina duomenų nuoseklumą ir padeda išvengti galimų klaidų tolimesniame apdorojime.
2. Daugkartinio naudojimo komponentų savybių (props) kūrimas
„React“ ir kitose vartotojo sąsajos sistemose (UI frameworks), susietieji tipai gali supaprastinti daugkartinio naudojimo komponentų savybių kūrimą. Tai ypač svarbu kuriant globalius vartotojo sąsajos komponentus, kurie turi prisitaikyti prie skirtingų lokalizacijų ir vartotojo sąsajų.
Pavyzdys: Lokalizacijos tvarkymas
interface TextProps {
textId: string;
defaultText: string;
locale: string;
}
type LocalizedTextProps = {
[K in keyof TextProps as `localized-${K}`]: TextProps[K];
};
Šiame kode naujas tipas LocalizedTextProps
prideda priešdėlį prie kiekvieno TextProps
savybės pavadinimo. Pavyzdžiui, textId
tampa localized-textId
, kas naudinga nustatant komponento savybes. Šį modelį galima naudoti generuojant savybes, kurios leidžia dinamiškai keisti tekstą atsižvelgiant į vartotojo lokalizaciją. Tai būtina kuriant daugiakalbes vartotojo sąsajas, kurios sklandžiai veikia skirtinguose regionuose ir kalbose, pavyzdžiui, elektroninės komercijos programose ar tarptautinėse socialinių tinklų platformose. Transformuotos savybės suteikia programuotojui daugiau kontrolės ties lokalizacija ir galimybę sukurti nuoseklią vartotojo patirtį visame pasaulyje.
3. Dinaminis formų generavimas
Susietieji tipai yra naudingi dinamiškai generuojant formos laukus pagal duomenų modelius. Globaliose programose tai gali būti naudinga kuriant formas, kurios prisitaiko prie skirtingų vartotojų rolių ar duomenų reikalavimų.
Pavyzdys: Automatinis formos laukų generavimas pagal objekto raktus
interface UserProfile {
firstName: string;
lastName: string;
email: string;
phoneNumber: string;
}
type FormFields = {
[K in keyof UserProfile]: {
label: string;
type: string;
required: boolean;
};
};
Tai leidžia apibrėžti formos struktūrą remiantis UserProfile
sąsajos savybėmis. Tai padeda išvengti poreikio rankiniu būdu apibrėžti formos laukus, pagerinant jūsų programos lankstumą ir priežiūrą.
Pažangios susietųjų tipų technikos
1. Raktų pervadinimas (Key Remapping)
„TypeScript 4.1“ pristatė raktų pervadinimą susietuosiuose tipuose. Tai leidžia pervadinti raktus transformuojant tipą. Tai ypač naudinga pritaikant tipus skirtingiems API reikalavimams arba kai norite sukurti vartotojui draugiškesnius savybių pavadinimus.
Pavyzdys: Savybių pervadinimas
interface Product {
productId: number;
productName: string;
productDescription: string;
price: number;
}
type ProductDto = {
[K in keyof Product as `dto_${K}`]: Product[K];
};
Tai pervadina kiekvieną Product
tipo savybę, pridedant priešdėlį dto_
. Tai vertinga, kai reikia susieti duomenų modelius ir API, kurie naudoja skirtingą pavadinimų suteikimo konvenciją. Tai svarbu tarptautinėje programinės įrangos kūrimo srityje, kur programos sąveikauja su keliomis vidinėmis sistemomis (back-end), kurios gali turėti specifines pavadinimų konvencijas, leidžiančias sklandžią integraciją.
2. Sąlyginis raktų pervadinimas
Galite derinti raktų pervadinimą su sąlyginiais tipais sudėtingesnėms transformacijoms, leidžiančioms pervadinti arba pašalinti savybes pagal tam tikrus kriterijus. Ši technika leidžia atlikti sudėtingas transformacijas.
Pavyzdys: Savybių pašalinimas iš DTO
interface Product {
id: number;
name: string;
description: string;
price: number;
category: string;
isActive: boolean;
}
type ProductDto = {
[K in keyof Product as K extends 'description' | 'isActive' ? never : K]: Product[K]
}
Čia description
ir isActive
savybės yra efektyviai pašalinamos iš sugeneruoto ProductDto
tipo, nes raktas išsisprendžia į never
, jei savybė yra „description“ arba „isActive“. Tai leidžia kurti specifinius duomenų perdavimo objektus (DTO), kuriuose yra tik būtini duomenys skirtingoms operacijoms. Toks selektyvus duomenų perdavimas yra gyvybiškai svarbus optimizavimui ir privatumui globalioje programoje. Duomenų perdavimo apribojimai užtikrina, kad tinklais siunčiami tik atitinkami duomenys, mažinant pralaidumo naudojimą ir gerinant vartotojo patirtį. Tai atitinka globalias privatumo taisykles.
3. Susietųjų tipų naudojimas su generiniais tipais (Generics)
Susietuosius tipus galima derinti su generiniais tipais, siekiant sukurti labai lanksčius ir daugkartinio naudojimo tipų apibrėžimus. Tai leidžia rašyti kodą, kuris gali apdoroti įvairius tipus, žymiai padidinant kodo pakartotinį naudojimą ir priežiūrą, kas ypač vertinga dideliuose projektuose ir tarptautinėse komandose.
Pavyzdys: Generinė funkcija objektų savybėms transformuoti
function transformObjectValues(obj: T, transform: (value: T[K]) => U): {
[P in keyof T]: U;
} {
const result: any = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
result[key] = transform(obj[key]);
}
}
return result;
}
interface Order {
id: number;
items: string[];
total: number;
}
const order: Order = {
id: 123,
items: ['apple', 'banana'],
total: 5.99,
};
const stringifiedOrder = transformObjectValues(order, (value) => String(value));
// stringifiedOrder: { id: string; items: string; total: string; }
Šiame pavyzdyje funkcija transformObjectValues
naudoja generinius tipus (T
, K
, ir U
), kad priimtų objektą (obj
) tipo T
ir transformavimo funkciją, kuri priima vieną savybę iš T ir grąžina reikšmę tipo U. Tuomet funkcija grąžina naują objektą, turintį tuos pačius raktus kaip ir originalus objektas, bet su reikšmėmis, kurios buvo transformuotos į tipą U.
Geriausios praktikos ir svarstymai
1. Tipų saugumas ir kodo priežiūra
Vienas didžiausių „TypeScript“ ir susietųjų tipų privalumų yra padidintas tipų saugumas. Apibrėždami aiškius tipus, klaidas aptinkate anksčiau kūrimo procese, mažindami vykdymo metu pasitaikančių klaidų tikimybę. Jie daro jūsų kodą lengviau suprantamą ir refaktorizuojamą, ypač dideliuose projektuose. Be to, susietųjų tipų naudojimas užtikrina, kad kodas yra mažiau linkęs į klaidas, kai programinė įranga plečiasi, prisitaikydama prie milijonų vartotojų poreikių visame pasaulyje.
2. Skaitomumas ir kodo stilius
Nors susietieji tipai gali būti galingi, svarbu juos rašyti aiškiai ir skaitomai. Naudokite prasmingus kintamųjų pavadinimus ir komentuokite kodą, kad paaiškintumėte sudėtingų transformacijų tikslą. Kodo aiškumas užtikrina, kad įvairių sričių programuotojai gali skaityti ir suprasti kodą. Nuoseklumas stiliuje, pavadinimų suteikimo konvencijose ir formatavime daro kodą prieinamesnį ir prisideda prie sklandesnio kūrimo proceso, ypač tarptautinėse komandose, kur skirtingi nariai dirba su skirtingomis programinės įrangos dalimis.
3. Perteklinis naudojimas ir sudėtingumas
Venkite perteklinio susietųjų tipų naudojimo. Nors jie yra galingi, jie gali padaryti kodą mažiau skaitomą, jei naudojami per daug arba kai yra paprastesnių sprendimų. Apsvarstykite, ar tiesmukas sąsajos apibrėžimas ar paprasta pagalbinė funkcija galėtų būti tinkamesnis sprendimas. Jei jūsų tipai tampa pernelyg sudėtingi, juos gali būti sunku suprasti ir prižiūrėti. Visada atsižvelkite į pusiausvyrą tarp tipų saugumo ir kodo skaitomumo. Šios pusiausvyros išlaikymas užtikrina, kad visi tarptautinės komandos nariai galėtų efektyviai skaityti, suprasti ir prižiūrėti kodo bazę.
4. Našumas
Susietieji tipai daugiausia veikia kompiliavimo metu atliekamą tipų patikrinimą ir paprastai nekelia didelio našumo praradimo vykdymo metu. Tačiau pernelyg sudėtingos tipų manipuliacijos potencialiai gali sulėtinti kompiliavimo procesą. Sumažinkite sudėtingumą ir atsižvelkite į poveikį kūrimo laikui, ypač dideliuose projektuose arba komandose, išsidėsčiusiose skirtingose laiko juostose ir turinčiose skirtingus išteklių apribojimus.
Išvada
„TypeScript“ susietieji tipai siūlo galingą įrankių rinkinį dinamiškam objektų formų transformavimui. Jie yra neįkainojami kuriant tipų saugų, prižiūrimą ir daugkartinio naudojimo kodą, ypač dirbant su sudėtingais duomenų modeliais, API sąveikomis ir vartotojo sąsajos komponentų kūrimu. Įvaldę susietuosius tipus, galite rašyti tvirtesnes ir labiau pritaikomas programas, kurdami geresnę programinę įrangą pasaulinei rinkai. Tarptautinėms komandoms ir pasauliniams projektams susietųjų tipų naudojimas užtikrina tvirtą kodo kokybę ir priežiūrą. Čia aptartos funkcijos yra labai svarbios kuriant pritaikomą ir mastelį keičiančią programinę įrangą, gerinant kodo priežiūrą ir kuriant geresnę patirtį vartotojams visame pasaulyje. Susietieji tipai palengvina kodo atnaujinimą, kai pridedamos ar modifikuojamos naujos funkcijos, API ar duomenų modeliai.