TypeScript mesterré válás – 10 haladó tipp és minta
Ha a TypeScript-et csak arra használod, hogy : string-et írj a változók mellé, akkor a felszínét kapargatod. A TypeScript egy rendkívül erős típusrendszer, amely képes a kódod logikájának egy részét fordítási időben ellenőrizni. Ebben a cikkben olyan haladó technikákat mutatok, amelyeket a mindennapi munkám során használok, és amiktől a kódod robusztusabb, öndokumentálóbb lesz.
1. Strict mode – kapcsold be, és ne kapcsold ki soha
A tsconfig.json-ban a "strict": true bekapcsolása 5 különböző ellenőrzést aktivál. Sokan kikapcsolják, mert „macera”, de pont ez véd meg a futásidejű hibáktól.
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true, // extra védelem
"exactOptionalPropertyTypes": true
}
}
2. Template Literal Types – dinamikus string típusok
Lehetővé teszik, hogy stringeket „matchelj” és új típusokat hozz létre belőlük.
type EventName = 'click' | 'focus' | 'blur';
type EventHandler = `on${Capitalize}`; // "onClick" | "onFocus" | "onBlur"
// API endpoint validáció
type ApiRoute = '/users' | '/posts' | '/comments';
type ApiUrl = `https://api.example.com${ApiRoute}`;
// Gyakorlati példa: CSS osztály generátor
type SpacingSize = 'sm' | 'md' | 'lg';
type SpacingClass = `p-${SpacingSize}`; // "p-sm" | "p-md" | "p-lg"
3. Discriminated Unions – a tökéletes state management
Amikor egy union típus minden tagjának van egy közös mezője (discriminant), a TypeScript leszűkíti a típust a mező alapján.
type AsyncState =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success'; data: T }
| { status: 'error'; error: Error };
function handleState(state: AsyncState) {
switch (state.status) {
case 'success':
console.log(state.data); // ✅ T típusú
break;
case 'error':
console.error(state.error.message); // ✅ Error
break;
// A default ágban a state típusa 'never' lesz, ha minden esetet lefedtél
}
}
4. satisfies operátor (TypeScript 4.9+)
Ellenőrzi, hogy egy objektum megfelel-e egy típusnak, de megtartja a literal típusokat.
// EDDIG: as const használata
const routes = {
home: '/',
about: '/about',
contact: '/contact'
} as const; // típus: { readonly home: "/"; readonly about: "/about"; ... }
// MOST: satisfies
const routes = {
home: '/',
about: '/about',
contact: '/contact'
} satisfies Record; // típus továbbra is a literal értékek
type HomeRoute = typeof routes.home; // "/" (nem string!)
5. Infer – típus kinyerése
Az infer kulcsszó lehetővé teszi, hogy egy feltételes típuson belül „kibonts” egy típust.
// Példa: kinyerjük egy Promise által visszaadott típust
type Awaited = T extends Promise ? U : T;
type Result = Awaited>; // string
// Függvény visszatérési típusának kinyerése
type ReturnType = T extends (...args: any[]) => infer R ? R : never;
function greet() { return "hello"; }
type GreetReturn = ReturnType; // string
6. Mapped Types – objektum típusok transzformálása
type ReadonlyDeep = {
readonly [K in keyof T]: T[K] extends object ? ReadonlyDeep : T[K];
};
type OptionalNullable = {
[K in keyof T]?: T[K] | null;
};
// Használat
interface User {
id: number;
profile: { name: string; age: number };
}
type ReadonlyUser = ReadonlyDeep;
// { readonly id: number; readonly profile: { readonly name: string; readonly age: number } }
7. Type Guards – saját típusellenőrző függvények
function isString(value: unknown): value is string {
return typeof value === 'string';
}
function isArrayOfStrings(value: unknown): value is string[] {
return Array.isArray(value) && value.every(item => typeof item === 'string');
}
// Használat
function process(data: unknown) {
if (isArrayOfStrings(data)) {
data.map(str => str.toUpperCase()); // ✅ data itt string[]
}
}
8. Conditional Types – ha-akkor a típusokban
type IsArray = T extends any[] ? true : false;
type A = IsArray; // true
type B = IsArray; // false
// Kivételkezelés típusokban
type ErrorOrSuccess = T extends { error: infer E } ? { error: E } : { success: T };
function getResult(val: T): ErrorOrSuccess {
// implementáció...
}
9. A never típus használata kimerítő ellenőrzésre
type Color = 'red' | 'green' | 'blue';
function getColorName(color: Color): string {
switch (color) {
case 'red': return 'Piros';
case 'green': return 'Zöld';
case 'blue': return 'Kék';
default:
// Ha új színt adsz a Color unionhoz, itt fordítási hiba lesz!
const _exhaustiveCheck: never = color;
throw new Error(`Ismeretlen szín: ${_exhaustiveCheck}`);
}
}
10. Utility Types – amiket érdemes fejből tudni
Partial<T>– minden opcionális leszRequired<T>– minden kötelezőPick<T, K>– csak bizonyos kulcsokOmit<T, K>– bizonyos kulcsok kihagyásaRecord<K, T>– objektum típus adott kulcsokkalExclude<U, V>– kivehető típusokExtract<U, V>– kivehető típusokNonNullable<T>– eltávolítja a null/undefined-etReturnType<T>– függvény visszatérési típusaParameters<T>– függvény paramétereinek tuple típusa
Egy gyakorlati példa az összes használatával:
interface ApiResponse {
data: T;
status: number;
message: string;
}
type PartialApiResponse = Partial>;
// { data?: string; status?: number; message?: string; }
type JustData = Pick, 'data'>;
// { data: number; }
Bónusz: TypeScript konfigurációk, amik sokat segítenek
{
"compilerOptions": {
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"allowUnreachableCode": false,
"forceConsistentCasingInFileNames": true
}
}
Remélem, ezek a tippek segítenek abban, hogy a TypeScript-et ne csak használd, hanem élvezd is! Gyakorold őket kisebb projektekben, és hamarosan a kódod magabiztosabb, olvashatóbb lesz. Ha van kedvenc trükköd, ami nincs a listában, oszd meg kommentben! 😊
Szabolcs Alex
Full Stack Developer & Tech Enthusiast
Szenvedélyes webfejlesztő, aki szeret megosztani tudását és tapasztalatait a modern webtechnológiákról. Ha kérdésed van, írj bátran!
