Visaptveroša rokasgrāmata par TypeScript jaudīgajiem kartētajiem un nosacījuma tipiem. Ietver praktiskus piemērus un sarežģītus lietojumus, lai veidotu robustas, tipdrošas lietojumprogrammas.
TypeScript kartēto un nosacījuma tipu meistarīga pārvaldīšana
TypeScript, kas ir JavaScript virskopa, piedāvā jaudīgas funkcijas robustu un uzturamu lietojumprogrammu izveidei. Starp šīm funkcijām kartētie tipi (Mapped Types) un nosacījuma tipi (Conditional Types) izceļas kā būtiski rīki padziļinātai tipu manipulācijai. Šī rokasgrāmata sniedz visaptverošu pārskatu par šiem jēdzieniem, izpētot to sintaksi, praktiskos pielietojumus un sarežģītākus lietošanas gadījumus. Neatkarīgi no tā, vai esat pieredzējis TypeScript izstrādātājs vai tikai sākat savu ceļu, šis raksts jūs apbruņos ar zināšanām, lai efektīvi izmantotu šīs funkcijas.
Kas ir kartētie tipi?
Kartētie tipi ļauj jums izveidot jaunus tipus, pārveidojot esošos. Tie iterē pāri esošā tipa īpašībām un katrai īpašībai piemēro pārveidojumu. Tas ir īpaši noderīgi, lai izveidotu esošo tipu variācijas, piemēram, padarot visas īpašības par neobligātām vai tikai lasāmām.
Pamata sintakse
Kartētā tipa sintakse ir šāda:
type NewType<T> = {
[K in keyof T]: Transformation;
};
T
: Ievades tips, kuru vēlaties kartēt.K in keyof T
: Iterē pāri katrai atslēgai ievades tipāT
.keyof T
izveido visuT
īpašību nosaukumu apvienojumu (union), unK
iterācijas laikā apzīmē katru atsevišķo atslēgu.Transformation
: Pārveidojums, ko vēlaties piemērot katrai īpašībai. Tas varētu būt modifikatora pievienošana (piemēram,readonly
vai?
), tipa maiņa vai kas cits.
Praktiski piemēri
Īpašību padarīšana par tikai lasāmām (Read-Only)
Pieņemsim, ka jums ir interfeiss, kas attēlo lietotāja profilu:
interface UserProfile {
name: string;
age: number;
email: string;
}
Jūs varat izveidot jaunu tipu, kurā visas īpašības ir tikai lasāmas:
type ReadOnlyUserProfile = {
readonly [K in keyof UserProfile]: UserProfile[K];
};
Tagad ReadOnlyUserProfile
būs tādas pašas īpašības kā UserProfile
, bet tās visas būs tikai lasāmas.
Īpašību padarīšana par neobligātām
Līdzīgi jūs varat padarīt visas īpašības par neobligātām:
type OptionalUserProfile = {
[K in keyof UserProfile]?: UserProfile[K];
};
OptionalUserProfile
būs visas UserProfile
īpašības, bet katra īpašība būs neobligāta.
Īpašību tipu modificēšana
Jūs varat arī modificēt katras īpašības tipu. Piemēram, jūs varat pārveidot visas īpašības par virknēm:
type StringifiedUserProfile = {
[K in keyof UserProfile]: string;
};
Šajā gadījumā visām StringifiedUserProfile
īpašībām būs tips string
.
Kas ir nosacījuma tipi?
Nosacījuma tipi ļauj definēt tipus, kas ir atkarīgi no nosacījuma. Tie nodrošina veidu, kā izteikt tipu attiecības, pamatojoties uz to, vai tips atbilst noteiktam ierobežojumam. Tas ir līdzīgi JavaScript ternārajam operatoram, bet paredzēts tipiem.
Pamata sintakse
Nosacījuma tipa sintakse ir šāda:
T extends U ? X : Y
T
: Pārbaudāmais tips.U
: Tips, koT
paplašina (nosacījums).X
: Tips, kas tiek atgriezts, jaT
paplašinaU
(nosacījums ir patiess).Y
: Tips, kas tiek atgriezts, jaT
nepaplašinaU
(nosacījums ir nepatiess).
Praktiski piemēri
Noteikšana, vai tips ir virkne
Izveidosim tipu, kas atgriež string
, ja ievades tips ir virkne, un number
pretējā gadījumā:
type StringOrNumber<T> = T extends string ? string : number;
type Result1 = StringOrNumber<string>; // string
type Result2 = StringOrNumber<number>; // number
type Result3 = StringOrNumber<boolean>; // number
Tipa izvilkšana no apvienojuma (Union)
Jūs varat izmantot nosacījuma tipus, lai izvilktu konkrētu tipu no apvienojuma tipa. Piemēram, lai izvilktu tipus, kas nav null-vērtības:
type NonNullable<T> = T extends null | undefined ? never : T;
type Result4 = NonNullable<string | null | undefined>; // string
Šeit, ja T
ir null
vai undefined
, tips kļūst par never
, ko pēc tam TypeScript apvienojuma tipu vienkāršošana izfiltrē.
Tipu secināšana (Inferring)
Nosacījuma tipus var izmantot arī, lai secinātu tipus, izmantojot atslēgvārdu infer
. Tas ļauj izvilkt tipu no sarežģītākas tipu struktūras.
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
function myFunction(x: number): string {
return x.toString();
}
type Result5 = ReturnType<typeof myFunction>; // string
Šajā piemērā ReturnType
izvelk funkcijas atgriešanas tipu. Tas pārbauda, vai T
ir funkcija, kas pieņem jebkādus argumentus un atgriež tipu R
. Ja tā ir, tas atgriež R
; pretējā gadījumā tas atgriež any
.
Kartēto un nosacījuma tipu apvienošana
Īstais kartēto un nosacījuma tipu spēks atklājas, tos apvienojot. Tas ļauj jums izveidot ļoti elastīgas un izteiksmīgas tipu transformācijas.
Piemērs: Dziļi tikai lasāms (Deep Readonly)
Biežs lietošanas gadījums ir izveidot tipu, kas padara visas objekta īpašības, ieskaitot ligzdotās īpašības, par tikai lasāmām. To var panākt, izmantojot rekursīvu nosacījuma tipu.
type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K];
};
interface Company {
name: string;
address: {
street: string;
city: string;
};
}
type ReadonlyCompany = DeepReadonly<Company>;
Šeit DeepReadonly
rekursīvi piemēro readonly
modifikatoru visām īpašībām un to ligzdotajām īpašībām. Ja īpašība ir objekts, tas rekursīvi izsauc DeepReadonly
šim objektam. Pretējā gadījumā tas vienkārši piemēro readonly
modifikatoru īpašībai.
Piemērs: Īpašību filtrēšana pēc tipa
Pieņemsim, ka vēlaties izveidot tipu, kas ietver tikai noteikta veida īpašības. Lai to panāktu, varat apvienot kartētos un nosacījuma tipus.
type FilterByType<T, U> = {
[K in keyof T as T[K] extends U ? K : never]: T[K];
};
interface Person {
name: string;
age: number;
isEmployed: boolean;
}
type StringProperties = FilterByType<Person, string>; // { name: string; }
type NonStringProperties = Omit<Person, keyof StringProperties>;
Šajā piemērā FilterByType
iterē pāri T
īpašībām un pārbauda, vai katras īpašības tips paplašina U
. Ja tā notiek, tas iekļauj īpašību rezultējošajā tipā; pretējā gadījumā tas to izslēdz, kartējot atslēgu uz never
. Ievērojiet "as" izmantošanu, lai pārkartētu atslēgas. Pēc tam mēs izmantojam `Omit` un `keyof StringProperties`, lai noņemtu virknes īpašības no sākotnējā interfeisa.
Padziļināti lietošanas gadījumi un modeļi
Papildus pamata piemēriem, kartētos un nosacījuma tipus var izmantot sarežģītākos scenārijos, lai izveidotu ļoti pielāgojamas un tipdrošas lietojumprogrammas.
Izplatošie nosacījuma tipi (Distributive Conditional Types)
Nosacījuma tipi ir izplatoši (distributive), kad pārbaudāmais tips ir apvienojuma tips. Tas nozīmē, ka nosacījums tiek piemērots katram apvienojuma dalībniekam atsevišķi, un rezultāti pēc tam tiek apvienoti jaunā apvienojuma tipā.
type ToArray<T> = T extends any ? T[] : never;
type Result6 = ToArray<string | number>; // string[] | number[]
Šajā piemērā ToArray
tiek piemērots katram apvienojuma string | number
dalībniekam atsevišķi, rezultātā iegūstot string[] | number[]
. Ja nosacījums nebūtu izplatošs, rezultāts būtu (string | number)[]
.
Utilīttipu izmantošana
TypeScript nodrošina vairākus iebūvētus utilīttipus, kas izmanto kartētos un nosacījuma tipus. Šos utilīttipus var izmantot kā pamatelementus sarežģītāku tipu transformācijām.
Partial<T>
: Padara visasT
īpašības par neobligātām.Required<T>
: Padara visasT
īpašības par obligātām.Readonly<T>
: Padara visasT
īpašības par tikai lasāmām.Pick<T, K>
: Atlasa īpašību kopuK
noT
.Omit<T, K>
: Noņem īpašību kopuK
noT
.Record<K, T>
: Konstruē tipu ar īpašību kopuK
, kam ir tipsT
.Exclude<T, U>
: Izslēdz noT
visus tipus, kas ir piešķiramiU
.Extract<T, U>
: Izvelk noT
visus tipus, kas ir piešķiramiU
.NonNullable<T>
: Izslēdznull
unundefined
noT
.Parameters<T>
: Iegūst funkcijas tipaT
parametrus.ReturnType<T>
: Iegūst funkcijas tipaT
atgriešanas tipu.InstanceType<T>
: Iegūst konstruktora funkcijas tipaT
instances tipu.
Šie utilīttipi ir jaudīgi rīki, kas var vienkāršot sarežģītas tipu manipulācijas. Piemēram, jūs varat apvienot Pick
un Partial
, lai izveidotu tipu, kas tikai noteiktas īpašības padara par neobligātām:
type Optional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
interface Product {
id: number;
name: string;
price: number;
description: string;
}
type OptionalDescriptionProduct = Optional<Product, "description">;
Šajā piemērā OptionalDescriptionProduct
ir visas Product
īpašības, bet description
īpašība ir neobligāta.
Veidņu literāļu tipu (Template Literal Types) izmantošana
Veidņu literāļu tipi ļauj jums izveidot tipus, pamatojoties uz virkņu literāļiem. Tos var izmantot kombinācijā ar kartētajiem un nosacījuma tipiem, lai izveidotu dinamiskas un izteiksmīgas tipu transformācijas. Piemēram, jūs varat izveidot tipu, kas visiem īpašību nosaukumiem pievieno noteiktu prefiksu:
type Prefix<T, P extends string> = {
[K in keyof T as `${P}${string & K}`]: T[K];
};
interface Settings {
apiUrl: string;
timeout: number;
}
type PrefixedSettings = Prefix<Settings, "data_">;
Šajā piemērā PrefixedSettings
būs īpašības data_apiUrl
un data_timeout
.
Labākās prakses un apsvērumi
- Ievērojiet vienkāršību: Lai gan kartētie un nosacījuma tipi ir jaudīgi, tie var arī padarīt jūsu kodu sarežģītāku. Centieties saglabāt savas tipu transformācijas pēc iespējas vienkāršākas.
- Izmantojiet utilīttipus: Kad vien iespējams, izmantojiet TypeScript iebūvētos utilīttipus. Tie ir labi pārbaudīti un var vienkāršot jūsu kodu.
- Dokumentējiet savus tipus: Skaidri dokumentējiet savas tipu transformācijas, īpaši, ja tās ir sarežģītas. Tas palīdzēs citiem izstrādātājiem saprast jūsu kodu.
- Pārbaudiet savus tipus: Izmantojiet TypeScript tipu pārbaudi, lai pārliecinātos, ka jūsu tipu transformācijas darbojas, kā paredzēts. Jūs varat rakstīt vienībtestus, lai pārbaudītu savu tipu uzvedību.
- Apsveriet veiktspēju: Sarežģītas tipu transformācijas var ietekmēt jūsu TypeScript kompilatora veiktspēju. Esiet uzmanīgi ar savu tipu sarežģītību un izvairieties no nevajadzīgiem aprēķiniem.
Noslēgums
Kartētie tipi un nosacījuma tipi ir jaudīgas TypeScript funkcijas, kas ļauj jums izveidot ļoti elastīgas un izteiksmīgas tipu transformācijas. Apgūstot šos jēdzienus, jūs varat uzlabot tipdrošību, uzturamību un kopējo kvalitāti savās TypeScript lietojumprogrammās. No vienkāršām transformācijām, piemēram, īpašību padarīšanas par neobligātām vai tikai lasāmām, līdz sarežģītām rekursīvām transformācijām un nosacījumu loģikai, šīs funkcijas nodrošina rīkus, kas nepieciešami, lai veidotu robustas un mērogojamas lietojumprogrammas. Turpiniet pētīt un eksperimentēt ar šīm funkcijām, lai atraisītu to pilno potenciālu un kļūtu par prasmīgāku TypeScript izstrādātāju.
Turpinot savu TypeScript ceļojumu, atcerieties izmantot pieejamo resursu bagātību, tostarp oficiālo TypeScript dokumentāciju, tiešsaistes kopienas un atvērtā koda projektus. Pieņemiet kartēto un nosacījuma tipu spēku, un jūs būsiet labi sagatavoti, lai risinātu pat vissarežģītākās ar tipiem saistītās problēmas.