SOLUTION: Challenge 2 - Set Up Path Aliases ============================================ Challenge: Create a tsconfig.json with path aliases (@utils, @types, @services). Set up dummy modules under each and import using the aliases. --- SOLUTION: // tsconfig.json { "compilerOptions": { "target": "ES2020", "module": "ESNext", "moduleResolution": "node", "baseUrl": ".", "paths": { "@types/*": ["src/types/*"], "@utils/*": ["src/utils/*"], "@services/*": ["src/services/*"], "@/*": ["src/*"] }, "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true }, "include": ["src"], "exclude": ["node_modules", "dist"] } --- // src/types/user.ts export interface User { id: number; name: string; email: string; } export interface LoginRequest { email: string; password: string; } --- // src/types/index.ts (barrel) export * from "./user"; --- // src/utils/format.ts export function formatDate(date: Date): string { return date.toLocaleDateString("en-US"); } export function formatCurrency(amount: number): string { return `$${amount.toFixed(2)}`; } --- // src/utils/validate.ts export function isValidEmail(email: string): boolean { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); } export function isStrongPassword(password: string): boolean { return password.length >= 8 && /[A-Z]/.test(password) && /[0-9]/.test(password); } --- // src/utils/index.ts (barrel) export * from "./format"; export * from "./validate"; --- // src/services/user-service.ts import { User, LoginRequest } from "@types"; export class UserService { async login(request: LoginRequest): Promise { // Simulate API call return { id: 1, name: "Alice", email: request.email }; } async getUser(id: number): Promise { // Simulate API call return { id, name: "User " + id, email: `user${id}@example.com` }; } } --- // src/services/index.ts (barrel) export { UserService } from "./user-service"; --- // src/app.ts (USAGE WITH PATH ALIASES) import { User, LoginRequest } from "@types"; import { formatDate, formatCurrency, isValidEmail, isStrongPassword } from "@utils"; import { UserService } from "@services"; // Use the imported types and utilities const loginRequest: LoginRequest = { email: "alice@example.com", password: "SecurePass123" }; if (!isValidEmail(loginRequest.email)) { console.error("Invalid email"); } if (!isStrongPassword(loginRequest.password)) { console.error("Weak password"); } const userService = new UserService(); userService.login(loginRequest).then((user: User) => { console.log(`Welcome ${user.name}!`); console.log(`Created: ${formatDate(new Date())}`); console.log(`Balance: ${formatCurrency(1000)}`); }); --- EXPLANATION: TSCONFIG SETUP: 1. baseUrl: "." — relative to project root 2. paths object — maps alias patterns to actual paths The pattern: "@utils/*": ["src/utils/*"] Means: @utils/format maps to src/utils/format.ts ALIASING PATTERNS: @types/* → src/types/* (types and interfaces) @utils/* → src/utils/* (utility functions) @services/* → src/services/* (business logic/services) @/* → src/* (catch-all for src) BENEFITS: 1. Short, readable imports 2. Refactor safely — change path mapping instead of updating imports 3. Project structure is clear from alias names 4. No ../../.. relative paths IMPORTING: Instead of: import { User } from "../../../../src/types/user"; Write: import { User } from "@types"; Much cleaner! --- TYPESCRIPT COMPILER & IDE SUPPORT: TypeScript resolves aliases at compile time. When you compile TypeScript to JavaScript, the imports are rewritten: TypeScript source: import { User } from "@types"; JavaScript output (if using CommonJS): const { User } = require("./src/types"); Your IDE (VS Code, etc.) understands these aliases too, so autocomplete works. --- WEBPACK / BUNDLER SETUP: If you're using a bundler (Webpack, Vite, etc.), you may need to configure the bundler separately. Most modern bundlers read tsconfig.json automatically: // Webpack example module.exports = { resolve: { alias: { "@types": path.resolve(__dirname, "src/types/"), "@utils": path.resolve(__dirname, "src/utils/"), "@services": path.resolve(__dirname, "src/services/") } } }; Vite and Next.js handle this automatically from tsconfig.json. --- REAL-WORLD PROJECTS: This pattern is standard in professional TypeScript projects: Create React App: "@/*": ["src/*"] NestJS: "@/*": ["src/*"] Angular: "~/*": ["src/*"] Path aliases make codebases professional and maintainable.