Lekcje modułu (2/2)
Typy pomocnicze (Utility)
TypeScript udostępnia kilka globalnych typów pomocniczych (Utility Types), które ułatwiają typowe transformacje typów. Typy te są generyczne i pozwalają na deklaratywne tworzenie nowych typów na podstawie już istniejących.
Pięć najczęściej używanych typów pomocniczych to:
1. Partial<T>
Czyni wszystkie właściwości typu T opcjonalnymi. Jest to niezwykle przydatne w funkcjach aktualizacji (update/patch), w których użytkownik może podać tylko podzbiór pól:
interface User {
id: number;
name: string;
email: string;
}
// Wszystkie właściwości User stają się opcjonalne: { id?: number; name?: string; email?: string; }
type UserUpdate = Partial<User>;2. Readonly<T>
Czyni wszystkie właściwości typu T tylko do odczytu (readonly). Każda próba ponownego przypisania właściwości spowoduje błąd kompilatora w czasie kompilacji:
interface Point {
x: number;
y: number;
}
const p: Readonly<Point> = { x: 10, y: 20 };
// p.x = 5; // Błąd: nie można przypisać wartości do 'x', ponieważ jest to właściwość tylko do odczytu3. Pick<T, Keys>
Tworzy typ, wybierając tylko określony zestaw kluczy (reprezentowany przez unię ciągów znaków) z typu T:
interface Article {
id: number;
title: string;
content: string;
views: number;
}
// Wybiera tylko 'title' i 'views': { title: string; views: number; }
type ArticlePreview = Pick<Article, 'title' | 'views'>;4. Omit<T, Keys>
Tworzy typ, usuwając określony zestaw kluczy z typu T. Jest to przeciwieństwo Pick:
interface Product {
id: number;
name: string;
price: number;
secretVendorCode: string;
}
// Usuwa 'secretVendorCode': { id: number; name: string; price: number; }
type PublicProduct = Omit<Product, 'secretVendorCode'>;5. Record<Keys, Type>
Tworzy typ obiektu, którego klucze to Keys, a wartości są typu Type. Jest bardzo przydatny do mapowania kluczy na wartości, reprezentowania słowników lub tablic mieszających (key-value maps):
type Page = 'home' | 'about' | 'contact';
interface PageInfo {
title: string;
}
// Tworzy słownik z kluczami 'home' | 'about' | 'contact' i wartościami PageInfo
const nav: Record<Page, PageInfo> = {
home: { title: 'Home Page' },
about: { title: 'About Us' },
contact: { title: 'Contact Us' },
};Spróbuj sam
Ćwiczenie 1: Aktualizacja profilu za pomocą Partial
Uzupełnij funkcję updateProfile, która przyjmuje oryginalny profil (Profile) oraz obiekt aktualizacji (updates), w którym wszystkie pola Profile są opcjonalne. Powinna zwracać nowy obiekt Profile łączący oryginalne właściwości z aktualizacjami.
Pokaż wskazówkę
Użyj typu pomocniczego Partial<Profile> dla parametru updates oraz operatora spread do połączenia obiektów: { ...original, ...updates }.
Rozwiązanie dostępne po 3 próbach
Ćwiczenie 2: Usuwanie poufnych pól za pomocą Omit
Dla danego typu UserAccount, zdefiniuj alias typu o nazwie SafeUser, który pomija poufną właściwość passwordHash.
Pokaż wskazówkę
Użyj type SafeUser = Omit<UserAccount, 'passwordHash'>; aby pominąć określone pole.
Rozwiązanie dostępne po 3 próbach
Ćwiczenie 3: Publiczna konfiguracja za pomocą Pick i Readonly
Dla danego typu AppConfig, zdefiniuj alias typu o nazwie PublicConfig, który jest wersją tylko do odczytu (Readonly) zawierającą tylko właściwości apiEndpoint oraz port wybrane za pomocą Pick.
Pokaż wskazówkę
Użyj type PublicConfig = Readonly<Pick<AppConfig, 'apiEndpoint' | 'port'>>;
Rozwiązanie dostępne po 3 próbach
Ćwiczenie 4: Rejestr użytkowników za pomocą Record i Readonly
Dla danego interfejsu User z polami id: number oraz name: string, utwórz typ ReadOnlyUser, który czyni wszystkie pola User tylko do odczytu. Następnie utwórz typ UserRegistry reprezentujący słownik, w którym kluczem jest ciąg znaków (np. tekstowy id), a wartością jest ReadOnlyUser.
Pokaż wskazówkę
Użyj Readonly<User> do zdefiniowania ReadOnlyUser oraz Record<string, ReadOnlyUser> dla słownika.
Rozwiązanie dostępne po 3 próbach