Deck 3 - TypeScript Type Safety + React Typing (objective)
Goal: write and review TS types like an evaluator.
You practice: sound types (unknown + narrowing), unions, generics, and React props/state/event typing.
Output style: 1 verdict sentence + 2-3 issues + safest fix.
Any vs unknown (define + why).
What is narrowing?
Define a user-defined type guard.
Discriminated union (define).
Exhaustive checks with never (why).
Interface vs type (practical rule).
Optional props and undefined (gotcha).
Readonly and immutability.
Literal types and ‘as const’.
satisfies operator (why).
Generics (define).
keyof / typeof / indexed access (define).
Utility types (common).
Function overloads (when).
Non-null assertion (!) (review rule).
Type assertions ‘as T’ (review rule).
React children typing (baseline).
React event typing (common).
Typing hooks (baseline).
Gotcha: external JSON typed as any.
const data = await res.json(); // data is any console.log(data.user.name.toUpperCase());
Verdict: FAIL
- Issue: res.json() is effectively any; no validation.
- Impact: runtime crash if shape differs.
- Fix: json -> unknown, then narrow/validate.
Gotcha: union not narrowed.
type ApiOk = { ok: true; user: { id: string; name: string } };
type ApiErr = { ok: false; error: string };
function f(res: ApiOk | ApiErr) {
return res.user.name;
}Verdict: FAIL
- Issue: res.user accessed without narrowing.
- Fix: if (res.ok) { … } else { … }.
Gotcha: using ‘as’ instead of narrowing.
const user = data as { id: string; name: string };
setName(user.name.toUpperCase());Verdict: FAIL
- Issue: assertion does not validate.
- Fix: validate unknown with a guard (or schema) before use.
Gotcha: optional prop assumed present.
type Props = { userId?: string };
function Profile({ userId }: Props) {
return <div>{userId.toUpperCase()}</div>;
}Verdict: FAIL
- Issue: userId can be undefined.
- Fix: make required or guard/default/conditional render.