TypeScript Programming Labs

Master TypeScript mastery: template literal types, type assertions, and project configuration.

Mastery Level - Module 6

Template literal types, type assertions & guards, and tsconfig.json configuration.

Lab 16: Template Literal Types
Mastery
Coding Challenge
Your Task: Master template literal types - TypeScript's way to create string types through concatenation and transformation. This enables powerful type-safe string manipulation.

Detailed Requirements:
1. Basic template literal types: Combine string literals:
type World = "world"; type Greeting = `hello ${World}`; // "hello world" type Color = "red" | "blue" | "green"; type Size = "small" | "large"; type ColoredSize = `${Size}-${Color}`; // "small-red" | "small-blue" | "small-green" | "large-red" | ...

2. String manipulation types: Built-in utility types:
type Upper = Uppercase<"hello">; // "HELLO" type Lower = Lowercase<"HELLO">; // "hello" type Cap = Capitalize<"hello">; // "Hello" type Uncap = Uncapitalize<"Hello">; // "hello"

3. Create event handler types: Common pattern in frameworks:
type Events = "click" | "focus" | "blur"; type EventHandlers = `on${Capitalize}`; // "onClick" | "onFocus" | "onBlur" interface Element { onClick: () => void; onFocus: () => void; onBlur: () => void; }

4. CSS property types: Type-safe CSS values:
type CSSUnit = "px" | "em" | "rem" | "%"; type CSSValue = `${number}${CSSUnit}`; const width: CSSValue = "100px"; // OK const height: CSSValue = "2.5em"; // OK // const bad: CSSValue = "100"; // Error!

5. Path builder types: Type-safe URL/path construction:
type APIVersion = "v1" | "v2"; type Resource = "users" | "posts" | "comments"; type APIPath = `/api/${APIVersion}/${Resource}`; // "/api/v1/users" | "/api/v1/posts" | "/api/v2/users" | ... type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE"; type Endpoint = `${HTTPMethod} ${APIPath}`; // "GET /api/v1/users" | "POST /api/v1/users" | ...

6. Extract and infer from template literals:
type ExtractRoute = T extends `/${infer First}/${infer Rest}` ? { first: First; rest: Rest } : never; type Route = ExtractRoute<"/users/123">; // { first: "users"; rest: "123" }

Expected Output:
Template literal: "hello world" Event handlers: onClick, onFocus, onBlur CSS value: 100px is valid API path: /api/v1/users Route extracted: users/123

Requirements Checklist

Create basic template literal type with ${}
Use Uppercase/Lowercase/Capitalize
Create event handler type pattern
Create CSS unit type pattern
Create API path type pattern
Test template literal types
Output
// Click "Run Code" to compile and execute
Hints & Tips
• Template literal: type T = `prefix ${SomeType} suffix`
• Uppercase: Uppercase<"hello"> = "HELLO"
• Capitalize: Capitalize<"hello"> = "Hello"
• Union expansion: Each union member is combined
• Infer in template: `${infer X}suffix`
Progress: 0/6
Score: 0/100
0%

Lab Results

Review feedback below

Lab 17: Type Assertions & Guards
Mastery
Coding Challenge
Your Task: Master type assertions and type guards for runtime type safety. Learn when to use each technique and how to narrow types effectively.

Detailed Requirements:
1. Type assertions (as keyword): Tell compiler what type something is:
// When you know more than TypeScript const input = document.getElementById("myInput") as HTMLInputElement; input.value = "Hello"; // Alternative syntax (not in JSX) const el = document.createElement("div"); // Double assertion for incompatible types (use sparingly!) const x = "hello" as unknown as number;

2. Non-null assertion (!): Assert value is not null/undefined:
function getLength(str: string | null): number { // Tell TypeScript str is definitely not null here return str!.length; } // Better: use optional chaining or guards instead const len = str?.length ?? 0;

3. Type guards with typeof: Narrow primitive types:
function padLeft(value: string | number, padding: string | number) { if (typeof padding === "number") { // padding is number here return " ".repeat(padding) + value; } // padding is string here return padding + value; }

4. Type guards with instanceof: Narrow class instances:
class Dog { bark() { console.log("Woof!"); } } class Cat { meow() { console.log("Meow!"); } } function makeSound(animal: Dog | Cat) { if (animal instanceof Dog) { animal.bark(); // TypeScript knows it's Dog } else { animal.meow(); // TypeScript knows it's Cat } }

5. Custom type guard functions: Create reusable type predicates:
interface Fish { swim(): void; } interface Bird { fly(): void; } // Type predicate: "pet is Fish" function isFish(pet: Fish | Bird): pet is Fish { return (pet as Fish).swim !== undefined; } function move(pet: Fish | Bird) { if (isFish(pet)) { pet.swim(); // TypeScript knows it's Fish } else { pet.fly(); // TypeScript knows it's Bird } }

6. Discriminated unions: Use a common property to distinguish:
interface Circle { kind: "circle"; radius: number; } interface Square { kind: "square"; side: number; } type Shape = Circle | Square; function getArea(shape: Shape): number { switch (shape.kind) { case "circle": return Math.PI * shape.radius ** 2; case "square": return shape.side ** 2; } }

Expected Output:
Type assertion: HTMLInputElement typeof guard: number path taken instanceof guard: Dog.bark() called Custom guard: isFish returned true Discriminated union: circle area = 78.54

Requirements Checklist

Use type assertion with "as" keyword
Use typeof type guard
Use instanceof type guard
Create custom type guard (is keyword)
Create discriminated union with kind
Test all type guards with console.log
Output
// Click "Run Code" to compile and execute
Hints & Tips
• Assertion: value as Type or <Type>value
• typeof: if (typeof x === "string")
• instanceof: if (x instanceof MyClass)
• Custom guard: function isX(val): val is X { }
• Discriminated: add kind: "typename" property
Progress: 0/6
Score: 0/100
0%

Lab Results

Review feedback below

Lab 18: tsconfig.json Configuration
Mastery
Coding Challenge
Your Task: Master TypeScript project configuration through tsconfig.json. Understanding compiler options is essential for any serious TypeScript project.

Detailed Requirements:
1. Basic tsconfig.json structure:
{ "compilerOptions": { "target": "ES2020", "module": "commonjs", "strict": true, "outDir": "./dist", "rootDir": "./src" }, "include": ["src/**/*"], "exclude": ["node_modules", "dist"] }

2. Strict mode options: Enable all strict checks:
{ "compilerOptions": { "strict": true, // Enable all strict options "noImplicitAny": true, // Error on implicit any "strictNullChecks": true, // null/undefined handled strictly "strictFunctionTypes": true, // Strict function type checking "strictBindCallApply": true, // Check bind/call/apply "strictPropertyInitialization": true, // Class props must be initialized "noImplicitThis": true, // Error on implicit this "alwaysStrict": true // Emit "use strict" } }

3. Module resolution options:
{ "compilerOptions": { "moduleResolution": "node", // Node.js style resolution "baseUrl": "./src", // Base for non-relative imports "paths": { // Path aliases "@utils/*": ["utils/*"], "@components/*": ["components/*"] }, "esModuleInterop": true, // Better CommonJS/ES interop "allowSyntheticDefaultImports": true } }

4. Output options:
{ "compilerOptions": { "outDir": "./dist", // Output directory "rootDir": "./src", // Root of source files "declaration": true, // Generate .d.ts files "declarationMap": true, // Source maps for .d.ts "sourceMap": true, // Generate source maps "inlineSources": true, // Include source in maps "removeComments": false // Keep comments in output } }

5. Type checking options:
{ "compilerOptions": { "noUnusedLocals": true, // Error on unused variables "noUnusedParameters": true, // Error on unused params "noImplicitReturns": true, // Error if not all paths return "noFallthroughCasesInSwitch": true,// Error on switch fallthrough "noUncheckedIndexedAccess": true, // Add undefined to index access "exactOptionalPropertyTypes": true // Strict optional properties } }

6. Project references (monorepo):
// tsconfig.json (root) { "files": [], "references": [ { "path": "./packages/core" }, { "path": "./packages/utils" } ] } // packages/core/tsconfig.json { "compilerOptions": { "composite": true, "declaration": true, "outDir": "./dist" }, "references": [ { "path": "../utils" } ] }

Expected Output:
tsconfig.json created Strict mode: enabled Module resolution: node Path aliases: configured Output: ./dist Type checking: strict

Requirements Checklist

Set target and module options
Enable strict mode
Configure moduleResolution and paths
Set outDir and rootDir
Add include/exclude arrays
Enable declaration generation
Output
// Click "Validate" to check your configuration
Hints & Tips
• target: "ES2020", "ES2021", "ESNext"
• module: "commonjs", "ES2020", "ESNext"
• strict: true enables all strict checks
• paths: "@alias/*": ["path/*"]
• include: ["src/**/*"] for glob patterns
Progress: 0/6
Score: 0/100
0%

Lab Results

Review feedback below

TypeScript Mastery Complete!

Congratulations! You've completed all 18 TypeScript labs covering beginner to mastery level concepts. You're now a TypeScript expert!