What you'll learn
Professional JavaScript combines threat-aware boundaries, gradual static typing, reviewed changes, and automated delivery. Security and types reduce different classes of uncertainty and work best together.
By the end of this lesson, you'll be able to:
- Prevent common web injection and request attacks
- Use TypeScript narrowing and generics
- Design a reviewable CI workflow
Core mental model
Use this decision table as a compact reference. Focus on what each tool means and when it earns its place in production code.
| Concept | What it means | Decision rule |
|---|---|---|
| Output safety | Data remains data in its destination context | Use safe APIs and context-correct encoding |
| Type narrowing | Runtime evidence refines a static union | Validate unknown input before treating it as domain data |
| CI gate | Automated checks protect the main branch | Run types, tests, lint, security, and build on every change |
Professional workflow
Build the behavior in small, observable steps. Each step should leave something you can inspect or test.
- Describe the secure typed delivery workflow boundary: inputs, outputs, state, timing, and expected failures.
- Implement the smallest correct path with names that expose intent.
- Add edge cases and failure handling before introducing abstractions.
- Verify behavior with realistic data and one deliberately adversarial example.
- Refactor only after the observable behavior is protected.
Make behavior observable
Guided code lab
Narrow unknown API data
The type guard performs runtime validation before TypeScript grants a trusted shape.
type Course = { id: string; title: string };
function isCourse(value: unknown): value is Course {
if (typeof value !== "object" || value === null) return false;
const record = value as Record<string, unknown>;
return typeof record.id === "string" && typeof record.title === "string";
}
const value: unknown = JSON.parse(payload);
if (!isCourse(value)) throw new TypeError("Invalid course payload");Keep untrusted text as text
The DOM API preserves the code/data boundary and avoids HTML parsing.
function renderComment(container, comment) {
const article = document.createElement("article");
const body = document.createElement("p");
body.textContent = comment.body;
article.append(body);
container.append(article);
}Production practice
Contract
Write down the secure typed delivery workflow quality target, ownership boundary, evidence, and acceptable tradeoffs.
Verification
Use repeatable automated checks plus a realistic end-to-end scenario; include failure and recovery behavior.
Operations
Track a small set of user-centered signals and revisit the decision when evidence changes.
Common failure mode
Independent workshop
Migrate one application slice to TypeScript and harden its data path.
Your finished workshop must include:
- unknown at the external boundary plus runtime validation
- No unsafe HTML sink
- CI checks for types, tests, build, and dependency risk
Definition of done
Recap & quick check
Key takeaways
- Keep code and data separate
- Validate every trust boundary
- TypeScript models compile-time guarantees
- CI makes quality repeatable
Quick check
1. What type best represents unvalidated external data?
2. Does TypeScript validate JSON at runtime?
3. Which DOM API safely renders ordinary text?
Keep the workshop. Later modules deliberately build on these decisions, so each exercise can become part of your final portfolio architecture.