Įsisavinkite TypeScript paslaugų tipus: galingus įrankius tipų transformacijoms, kurie pagerina kodo pakartotinį naudojimą ir padidina tipų saugumą jūsų programose.
TypeScript paslaugų tipai: integruoti tipų manipuliavimo įrankiai
TypeScript yra galinga kalba, kuri į JavaScript įneša statinį tipizavimą. Viena iš jos pagrindinių savybių yra gebėjimas manipuliuoti tipais, leidžiantis programuotojams kurti tvirtesnį ir lengviau prižiūrimą kodą. TypeScript pateikia integruotų paslaugų tipų rinkinį, kuris supaprastina įprastas tipų transformacijas. Šie paslaugų tipai yra neįkainojami įrankiai, didinantys tipų saugumą, gerinantys kodo pakartotinį naudojimą ir optimizuojantys jūsų kūrimo eigą. Šis išsamus vadovas nagrinėja svarbiausius TypeScript paslaugų tipus, pateikdamas praktinių pavyzdžių ir veiksmingų įžvalgų, kurios padės jums juos įvaldyti.
Kas yra TypeScript paslaugų tipai?
Paslaugų tipai yra iš anksto apibrėžti tipų operatoriai, kurie transformuoja esamus tipus į naujus. Jie yra integruoti į TypeScript kalbą ir suteikia glaustą bei deklaratyvų būdą atlikti įprastas tipų manipuliacijas. Naudojant paslaugų tipus galima žymiai sumažinti pasikartojančio kodo kiekį ir padaryti jūsų tipų apibrėžimus išraiškingesnius bei lengviau suprantamus.
Galvokite apie juos kaip apie funkcijas, kurios veikia su tipais, o ne su reikšmėmis. Jos priima tipą kaip įvesties duomenis ir grąžina modifikuotą tipą kaip išvesties duomenis. Tai leidžia jums sukurti sudėtingus tipų ryšius ir transformacijas su minimaliu kodu.
Kodėl naudoti paslaugų tipus?
Yra keletas svarių priežasčių, kodėl verta įtraukti paslaugų tipus į savo TypeScript projektus:
- Padidintas tipų saugumas: Paslaugų tipai padeda taikyti griežtesnius tipų apribojimus, sumažinant vykdymo laiko klaidų tikimybę ir gerinant bendrą kodo patikimumą.
- Pagerintas kodo pakartotinis naudojimas: Naudodami paslaugų tipus, galite kurti bendrinius komponentus ir funkcijas, kurios veikia su įvairiais tipais, skatinant kodo pakartotinį naudojimą ir mažinant pertekliškumą.
- Sumažintas pasikartojančio kodo kiekis: Paslaugų tipai suteikia glaustą ir deklaratyvų būdą atlikti įprastas tipų transformacijas, sumažinant pasikartojančio kodo, kurį reikia parašyti, kiekį.
- Pagerintas skaitomumas: Paslaugų tipai daro jūsų tipų apibrėžimus išraiškingesnius ir lengviau suprantamus, gerinant jūsų kodo skaitomumą ir priežiūrą.
Esminiai TypeScript paslaugų tipai
Panagrinėkime kai kuriuos dažniausiai naudojamus ir naudingiausius paslaugų tipus TypeScript kalboje. Aptarsime jų paskirtį, sintaksę ir pateiksime praktinių pavyzdžių, iliustruojančių jų naudojimą.
1. Partial<T>
Paslaugos tipas Partial<T>
visas tipo T
savybes paverčia nebūtinomis. Tai naudinga, kai norite sukurti naują tipą, kuris turi kai kurias arba visas esamo tipo savybes, bet nenorite reikalauti, kad visos jos būtų pateiktos.
Sintaksė:
type Partial<T> = { [P in keyof T]?: T[P]; };
Pavyzdys:
interface User {
id: number;
name: string;
email: string;
}
type OptionalUser = Partial<User>; // Visos savybės dabar yra nebūtinos
const partialUser: OptionalUser = {
name: "Alice", // Pateikiama tik vardo savybė
};
Panaudojimo atvejis: Objekto atnaujinimas tik su tam tikromis savybėmis. Pavyzdžiui, įsivaizduokite vartotojo profilio atnaujinimo formą. Jūs nenorite reikalauti, kad vartotojai vienu metu atnaujintų visus laukus.
2. Required<T>
Paslaugos tipas Required<T>
visas tipo T
savybes paverčia būtinomis. Tai yra Partial<T>
priešingybė. Tai naudinga, kai turite tipą su nebūtinomis savybėmis ir norite užtikrinti, kad visos savybės būtų pateiktos.
Sintaksė:
type Required<T> = { [P in keyof T]-?: T[P]; };
Pavyzdys:
interface Config {
apiKey?: string;
apiUrl?: string;
}
type CompleteConfig = Required<Config>; // Visos savybės dabar yra būtinos
const config: CompleteConfig = {
apiKey: "your-api-key",
apiUrl: "https://example.com/api",
};
Panaudojimo atvejis: Užtikrinimas, kad visi konfigūracijos nustatymai būtų pateikti prieš paleidžiant programą. Tai gali padėti išvengti vykdymo laiko klaidų, kurias sukelia trūkstami ar neapibrėžti nustatymai.
3. Readonly<T>
Paslaugos tipas Readonly<T>
visas tipo T
savybes paverčia tik skaitomomis (angl. readonly). Tai apsaugo nuo atsitiktinio objekto savybių modifikavimo po jo sukūrimo. Tai skatina nekintamumą (angl. immutability) ir gerina jūsų kodo nuspėjamumą.
Sintaksė:
type Readonly<T> = { readonly [P in keyof T]: T[P]; };
Pavyzdys:
interface Product {
id: number;
name: string;
price: number;
}
type ImmutableProduct = Readonly<Product>; // Visos savybės dabar yra tik skaitomos
const product: ImmutableProduct = {
id: 123,
name: "Example Product",
price: 25.99,
};
// product.price = 29.99; // Klaida: Negalima priskirti reikšmės 'price', nes tai yra tik skaitoma savybė.
Panaudojimo atvejis: Nekintamų duomenų struktūrų, tokių kaip konfigūracijos objektai ar duomenų perdavimo objektai (DTO), kūrimas, kurių nereikėtų modifikuoti po sukūrimo. Tai ypač naudinga funkcinio programavimo paradigmose.
4. Pick<T, K extends keyof T>
Paslaugos tipas Pick<T, K extends keyof T>
sukuria naują tipą, pasirinkdamas savybių rinkinį K
iš tipo T
. Tai naudinga, kai jums reikia tik dalies esamo tipo savybių.
Sintaksė:
type Pick<T, K extends keyof T> = { [P in K]: T[P]; };
Pavyzdys:
interface Employee {
id: number;
name: string;
department: string;
salary: number;
}
type EmployeeNameAndDepartment = Pick<Employee, "name" | "department">; // Pasirenkamas tik vardas ir departamentas
const employeeInfo: EmployeeNameAndDepartment = {
name: "Bob",
department: "Engineering",
};
Panaudojimo atvejis: Specializuotų duomenų perdavimo objektų (DTO) kūrimas, kuriuose yra tik konkrečiai operacijai reikalingi duomenys. Tai gali pagerinti našumą ir sumažinti per tinklą perduodamų duomenų kiekį. Įsivaizduokite, kad siunčiate vartotojo duomenis klientui, bet neįtraukiate jautrios informacijos, pvz., atlyginimo. Galėtumėte naudoti Pick, kad išsiųstumėte tik `id` ir `name`.
5. Omit<T, K extends keyof any>
Paslaugos tipas Omit<T, K extends keyof any>
sukuria naują tipą, praleisdamas savybių rinkinį K
iš tipo T
. Tai yra Pick<T, K extends keyof T>
priešingybė ir naudinga, kai norite iš esamo tipo pašalinti tam tikras savybes.
Sintaksė:
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
Pavyzdys:
interface Event {
id: number;
title: string;
description: string;
date: Date;
location: string;
}
type EventSummary = Omit<Event, "description" | "location">; // Praleidžiamas aprašymas ir vieta
const eventPreview: EventSummary = {
id: 1,
title: "Conference",
date: new Date(),
};
Panaudojimo atvejis: Supaprastintų duomenų modelių versijų kūrimas konkretiems tikslams, pavyzdžiui, renginio santraukos rodymas neįtraukiant viso aprašymo ir vietos. Tai taip pat galima naudoti jautriems laukams pašalinti prieš siunčiant duomenis klientui.
6. Exclude<T, U>
Paslaugos tipas Exclude<T, U>
sukuria naują tipą, iš tipo T
pašalindamas visus tipus, kurie yra priskiriami tipui U
. Tai naudinga, kai norite pašalinti tam tikrus tipus iš jungtinio tipo (angl. union type).
Sintaksė:
type Exclude<T, U> = T extends U ? never : T;
Pavyzdys:
type AllowedFileTypes = "image" | "video" | "audio" | "document";
type MediaFileTypes = "image" | "video" | "audio";
type DocumentFileTypes = Exclude<AllowedFileTypes, MediaFileTypes>; // "document"
const fileType: DocumentFileTypes = "document";
Panaudojimo atvejis: Jungtinio tipo filtravimas, siekiant pašalinti konkrečius tipus, kurie tam tikrame kontekste nėra aktualūs. Pavyzdžiui, galbūt norėsite pašalinti tam tikrus failų tipus iš leistinų failų tipų sąrašo.
7. Extract<T, U>
Paslaugos tipas Extract<T, U>
sukuria naują tipą, iš tipo T
išskirdamas visus tipus, kurie yra priskiriami tipui U
. Tai yra Exclude<T, U>
priešingybė ir naudinga, kai norite pasirinkti konkrečius tipus iš jungtinio tipo.
Sintaksė:
type Extract<T, U> = T extends U ? T : never;
Pavyzdys:
type InputTypes = string | number | boolean | null | undefined;
type PrimitiveTypes = string | number | boolean;
type NonNullablePrimitives = Extract<InputTypes, PrimitiveTypes>; // string | number | boolean
const value: NonNullablePrimitives = "hello";
Panaudojimo atvejis: Konkrečių tipų pasirinkimas iš jungtinio tipo pagal tam tikrus kriterijus. Pavyzdžiui, galbūt norėsite išskirti visus primityvius tipus iš jungtinio tipo, kuris apima tiek primityvius, tiek objektų tipus.
8. NonNullable<T>
Paslaugos tipas NonNullable<T>
sukuria naują tipą, iš tipo T
pašalindamas null
ir undefined
. Tai naudinga, kai norite užtikrinti, kad tipas negali būti null
ar undefined
.
Sintaksė:
type NonNullable<T> = T extends null | undefined ? never : T;
Pavyzdys:
type MaybeString = string | null | undefined;
type DefinitelyString = NonNullable<MaybeString>; // string
const message: DefinitelyString = "Hello, world!";
Panaudojimo atvejis: Užtikrinimas, kad reikšmė nėra null
ar undefined
prieš atliekant su ja operaciją. Tai gali padėti išvengti vykdymo laiko klaidų, kurias sukelia netikėtos null ar undefined reikšmės. Apsvarstykite scenarijų, kai reikia apdoroti vartotojo adresą ir yra labai svarbu, kad adresas nebūtų null prieš bet kokią operaciją.
9. ReturnType<T extends (...args: any) => any>
Paslaugos tipas ReturnType<T extends (...args: any) => any>
išskiria funkcijos tipo T
grąžinimo tipą. Tai naudinga, kai norite žinoti, kokio tipo reikšmę funkcija grąžina.
Sintaksė:
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
Pavyzdys:
function fetchData(url: string): Promise<{ data: any }> {
return fetch(url).then(response => response.json());
}
type FetchDataReturnType = ReturnType<typeof fetchData>; // Promise<{ data: any }>
async function processData(data: FetchDataReturnType) {
// ...
}
Panaudojimo atvejis: Funkcijos grąžinamos reikšmės tipo nustatymas, ypač dirbant su asinchroninėmis operacijomis ar sudėtingomis funkcijų signatūromis. Tai leidžia užtikrinti, kad teisingai tvarkote grąžintą reikšmę.
10. Parameters<T extends (...args: any) => any>
Paslaugos tipas Parameters<T extends (...args: any) => any>
išskiria funkcijos tipo T
parametrų tipus kaip kortežą (angl. tuple). Tai naudinga, kai norite žinoti, kokių tipų argumentus funkcija priima.
Sintaksė:
type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;
Pavyzdys:
function createUser(name: string, age: number, email: string): void {
// ...
}
type CreateUserParams = Parameters<typeof createUser>; // [string, number, string]
function logUser(...args: CreateUserParams) {
console.log("Creating user with:", args);
}
Panaudojimo atvejis: Funkcijos priimamų argumentų tipų nustatymas, kas gali būti naudinga kuriant bendrines funkcijas ar dekoratorius, kurie turi veikti su skirtingų signatūrų funkcijomis. Tai padeda užtikrinti tipų saugumą dinamiškai perduodant argumentus funkcijai.
11. ConstructorParameters<T extends abstract new (...args: any) => any>
Paslaugos tipas ConstructorParameters<T extends abstract new (...args: any) => any>
išskiria konstruktoriaus funkcijos tipo T
parametrų tipus kaip kortežą. Tai naudinga, kai norite žinoti, kokių tipų argumentus konstruktorius priima.
Sintaksė:
type ConstructorParameters<T extends abstract new (...args: any) => any> = T extends abstract new (...args: infer P) => any ? P : never;
Pavyzdys:
class Logger {
constructor(public prefix: string, public enabled: boolean) {}
log(message: string) {
if (this.enabled) {
console.log(`${this.prefix}: ${message}`);
}
}
}
type LoggerConstructorParams = ConstructorParameters<typeof Logger>; // [string, boolean]
function createLogger(...args: LoggerConstructorParams) {
return new Logger(...args);
}
Panaudojimo atvejis: Panašus į Parameters
, bet skirtas specialiai konstruktorių funkcijoms. Tai padeda kuriant gamyklas (angl. factories) ar priklausomybių injekcijos sistemas, kur reikia dinamiškai kurti klasių egzempliorius su skirtingomis konstruktorių signatūromis.
12. InstanceType<T extends abstract new (...args: any) => any>
Paslaugos tipas InstanceType<T extends abstract new (...args: any) => any>
išskiria konstruktoriaus funkcijos tipo T
egzemplioriaus tipą. Tai naudinga, kai norite žinoti, kokio tipo objektą sukuria konstruktorius.
Sintaksė:
type InstanceType<T extends abstract new (...args: any) => any> = T extends abstract new (...args: any) => infer R ? R : any;
Pavyzdys:
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}
type GreeterInstance = InstanceType<typeof Greeter>; // Greeter
const myGreeter: GreeterInstance = new Greeter("World");
console.log(myGreeter.greet());
Panaudojimo atvejis: Konstruktoriaus sukurto objekto tipo nustatymas, kas naudinga dirbant su paveldėjimu ar polimorfizmu. Tai suteikia tipų saugumo požiūriu patikimą būdą nurodyti klasės egzempliorių.
13. Record<K extends keyof any, T>
Paslaugos tipas Record<K extends keyof any, T>
sukuria objekto tipą, kurio savybių raktai yra K
, o savybių reikšmės yra T
. Tai naudinga kuriant žodyno tipo tipus, kai iš anksto žinote raktus.
Sintaksė:
type Record<K extends keyof any, T> = { [P in K]: T; };
Pavyzdys:
type CountryCode = "US" | "CA" | "GB" | "DE";
type CurrencyMap = Record<CountryCode, string>; // { US: string; CA: string; GB: string; DE: string; }
const currencies: CurrencyMap = {
US: "USD",
CA: "CAD",
GB: "GBP",
DE: "EUR",
};
Panaudojimo atvejis: Žodyno tipo objektų kūrimas, kai turite fiksuotą raktų rinkinį ir norite užtikrinti, kad visų raktų reikšmės būtų tam tikro tipo. Tai dažnai pasitaiko dirbant su konfigūracijos failais, duomenų atvaizdavimais ar paieškos lentelėmis.
Individualūs paslaugų tipai
Nors TypeScript integruoti paslaugų tipai yra galingi, taip pat galite kurti savo individualius paslaugų tipus, kad patenkintumėte specifinius savo projektų poreikius. Tai leidžia jums apgaubti sudėtingas tipų transformacijas ir pakartotinai jas naudoti visame savo kode.
Pavyzdys:
// Paslaugos tipas, skirtas gauti objekto raktus, turinčius konkretų tipą
type KeysOfType<T, U> = { [K in keyof T]: T[K] extends U ? K : never }[keyof T];
interface Person {
name: string;
age: number;
address: string;
phoneNumber: number;
}
type StringKeys = KeysOfType<Person, string>; // "name" | "address"
Geriausios paslaugų tipų naudojimo praktikos
- Naudokite aprašomuosius pavadinimus: Suteikite savo paslaugų tipams prasmingus pavadinimus, kurie aiškiai nurodo jų paskirtį. Tai pagerina jūsų kodo skaitomumą ir priežiūrą.
- Dokumentuokite savo paslaugų tipus: Pridėkite komentarus, paaiškinančius, ką jūsų paslaugų tipai daro ir kaip juos reikėtų naudoti. Tai padeda kitiems programuotojams suprasti jūsų kodą ir teisingai jį naudoti.
- Laikykitės paprastumo: Venkite kurti pernelyg sudėtingus paslaugų tipus, kuriuos sunku suprasti. Suskaidykite sudėtingas transformacijas į mažesnius, lengviau valdomus paslaugų tipus.
- Testuokite savo paslaugų tipus: Rašykite vienetinius testus (angl. unit tests), kad užtikrintumėte, jog jūsų paslaugų tipai veikia teisingai. Tai padeda išvengti netikėtų klaidų ir užtikrina, kad jūsų tipai elgiasi taip, kaip tikėtasi.
- Atsižvelkite į našumą: Nors paslaugų tipai paprastai neturi didelės įtakos našumui, būkite atidūs savo tipų transformacijų sudėtingumui, ypač dideliuose projektuose.
Išvados
TypeScript paslaugų tipai yra galingi įrankiai, kurie gali žymiai pagerinti jūsų kodo tipų saugumą, pakartotinį naudojimą ir priežiūrą. Įvaldę šiuos paslaugų tipus, galite rašyti tvirtesnes ir išraiškingesnes TypeScript programas. Šiame vadove buvo apžvelgti svarbiausi TypeScript paslaugų tipai, pateikti praktiniai pavyzdžiai ir veiksmingos įžvalgos, kurios padės jums juos įtraukti į savo projektus.
Nepamirškite eksperimentuoti su šiais paslaugų tipais ir tyrinėti, kaip juos galima panaudoti sprendžiant konkrečias problemas savo kode. Kai geriau su jais susipažinsite, pastebėsite, kad vis dažniau juos naudojate kurdami švaresnes, lengviau prižiūrimas ir tipų požiūriu saugesnes TypeScript programas. Nesvarbu, ar kuriate žiniatinklio programas, serverio programas, ar bet ką tarp jų, paslaugų tipai suteikia vertingą įrankių rinkinį, skirtą pagerinti jūsų kūrimo eigą ir kodo kokybę. Naudodamiesi šiais integruotais tipų manipuliavimo įrankiais, galite atskleisti visą TypeScript potencialą ir rašyti kodą, kuris yra ir išraiškingas, ir tvirtas.