SOLUTION: Challenge 2 - Build a Utility Type ============================================== Challenge: Create a utility type GetType that takes an object type and a key, and returns the type of that property. Test it on a sample interface. --- SOLUTION: // The utility type type GetType = T[K]; // Alternative version with conditional (more explicit) type GetTypeConditional = K extends keyof T ? T[K] : never; // Test it on an interface interface User { id: number; name: string; email: string; isAdmin: boolean; } // Extract individual property types type UserId = GetType; // number type UserName = GetType; // string type UserEmail = GetType; // string type UserAdmin = GetType; // boolean // Use it in function signatures function processId(id: UserId) { console.log(`User ID: ${id}`); } function processName(name: UserName) { console.log(`User name: ${name}`); } // Real-world use: data validation type ValidationRules = { [K in keyof User]: (value: GetType) => boolean; }; const rules: ValidationRules = { id: (id) => typeof id === "number" && id > 0, name: (name) => typeof name === "string" && name.length > 0, email: (email) => typeof email === "string" && email.includes("@"), isAdmin: (isAdmin) => typeof isAdmin === "boolean" }; --- EXPLANATION: SIMPLE VERSION (T[K]): This is called "indexed access" or "lookup type." T[K] accesses the type of property K in object T. Since K is constrained to keyof T, the access is always valid. CONDITIONAL VERSION (T[K] ? T[K] : never): Same result, but explicitly checks if K is a key first. Useful when you're not sure K extends keyof T (defensive programming). If K is a valid key, return T[K]; otherwise never (impossible type). WHY keyof T IN THE CONSTRAINT: Without it, TypeScript wouldn't know that K is a valid key. K could be anything, and T[K] would be unknown. The constraint guarantees K exists on T. REAL-WORLD PATTERN: The validation example shows how GetType enables building maps of property-specific handlers (validators, serializers, etc.). Each handler gets the exact type for its property—no type casting needed. --- ADVANCED: Combining with other utilities You could extend this to build more complex types: // Get all values (union of all property types) type GetAllTypes = GetType; type UserValues = GetAllTypes; // number | string | boolean // Get all types for specific keys type GetMultiple = GetType[]; type IdArray = GetMultiple; // number[] These patterns are the building blocks of TypeScript's ecosystem.