Loading content…
Loading content…
Master advanced static type checking using TypeScript Generics, type guards, and native utility type configurations
string, number). Real-world projects use dynamic generic arguments to type reusable API handlers, write custom type narrowing guards to prevent runtime crashes, and apply utility types to represent subsets of existing interface objects.<T>)any (which disables type safety), use a type parameter T:// Reusable identity function
function apiResponseWrapper<T>(data: T, status: number) {
return {
data,
status,
timestamp: new Date()
};
}
// Explicit usage
const stringResponse = apiResponseWrapper<string>("Success", 200);
// stringResponse.data is typed as string!
// Implicit usage (TypeScript infers type automatically)
const userResponse = apiResponseWrapper({ id: 1, name: "Bob" }, 200);
// userResponse.data is typed as { id: number; name: string }!
typeof & instanceoffunction processId(id: string | number) {
if (typeof id === "string") {
// TypeScript knows 'id' is a string inside this block!
return id.toUpperCase();
}
// TypeScript knows 'id' is a number here
return id.toFixed(0);
}
parameterName is Type):interface Admin {
role: "admin";
permissions: string[];
}
interface User {
role: "user";
email: string;
}
// Custom Type Guard
function isAdmin(profile: Admin | User): profile is Admin {
return profile.role === "admin";
}
function handleAccess(profile: Admin | User) {
if (isAdmin(profile)) {
// Safe: profile typed as Admin inside this scope!
console.log(profile.permissions);
} else {
// Safe: profile typed as User
console.log(profile.email);
}
}
Partial<T>: Makes all properties in T optional.Omit<T, K>: Creates a type by removing properties list K from T.Pick<T, K>: Creates a type by selecting only properties list K from T.Record<K, T>: Creates an object type with keys of type K and values of type T.interface UserProfile {
id: string;
username: string;
email: string;
avatarUrl: string;
createdAt: Date;
}
// 1. Partial: Ideal for update/patch endpoints
type ProfileUpdateInput = Partial<UserProfile>; // All properties optional
// 2. Omit: Ideal for creating records where database autogenerates fields
type NewProfileInput = Omit<UserProfile, "id" | "createdAt">;
// 3. Pick: Ideal for selecting specific subset data cards
type PreviewProfile = Pick<UserProfile, "username" | "avatarUrl">;
// 4. Record: Ideal for mapping key-value dictionary tables
const usersDict: Record<string, UserProfile> = {
"user_101": { id: "101", username: "alice", email: "a@test.com", avatarUrl: "/url", createdAt: new Date() }
};
tsconfig.json)tsconfig.json with strict compilation standards:{
"compilerOptions": {
"strict": true, /* Enable all strict type-checking options */
"noImplicitAny": true, /* Raise error on expressions with implied any type */
"strictNullChecks": true, /* Null and undefined get unique distinct types */
"noUnusedLocals": true, /* Report errors on unused local variables */
"noUnusedParameters": true, /* Report errors on unused function parameters */
"noImplicitReturns": true, /* Ensure all code paths in function return a value */
"exactOptionalPropertyTypes": true /* Optional properties are not undefined */
}
}
Senior Developer Wisdom
strictNullChecks: true is the most impactful setting for reducing production bugs. It forces developers to handle null and undefined cases explicitly, eliminating "Cannot read property 'X' of undefined" crashes.Common Pitfall
as keyword) to bypass compiler warnings. Assertions force the compiler to trust you, but do not perform any runtime checks, meaning errors will simply manifest as runtime crashes. Use proper type guards instead.TypeScript Advanced Checklist
Marking it complete updates your roadmap progress percentage.