Anatomy of TypeScript Code — Naming the Parts¶
An evergreen reference for the whole React/TypeScript pass and the capstone. You can write TypeScript and React before you can talk about it — this sheet closes that gap. It points at every token in the three files you build for one feature — an interface, an API module, and a list component — and names what each is: interface, property, type, object, method, function, hook, parameter, argument, and the rest.
Keep it open from React Lesson 3–4 (your first component and your first fetch) onward. There's a blank quiz version for practice. This is the TypeScript companion to the API pass's Anatomy of C# Code — same idea, different language: C# concentrates everything in a class; React spreads it across a small interface, a plain object of functions, and a function that returns UI.
All three specimens are the Staff feature — the exact code you write in Lessons 3–4.
Specimen A — a model interface (staff/IStaff.ts)¶
An interface describes the shape of your data — which properties an object has and what type each one is. It's TypeScript's answer to a C# data class, with no methods: just properties.
// src/staff/IStaff.ts
export interface IStaff { // ① ②
id: number | undefined; // ③ ④
firstName: string; // ⑤
lastName: string;
username: string;
isManager: boolean; // ⑥
isAdmin: boolean;
}
| # | Token | What it is |
|---|---|---|
| ① | export |
Named export — makes IStaff importable from other files (matched by import { IStaff }) |
| ② | IStaff |
Interface — the shape of a staff object; a type you define (React's answer to a data class) |
| ③ | id |
Property — one named field in the shape |
| ④ | number \| undefined |
Union type — the value is either a number or undefined (a new staff has no id until the server assigns one) |
| ⑤ | string |
Type annotation — the type written after the :; string here is a primitive type |
| ⑥ | boolean |
Primitive type — a built-in true/false type |
An interface is a type, not a value — it exists only while TypeScript checks your code and is erased from the JavaScript that actually runs. You never create an
IStaffwithnew; you create plain objects that match its shape (see Specimen C).
Specimen B — an API module (staff/StaffAPI.ts)¶
An API module is a plain object that groups an entity's fetch calls as methods,
so components call staffAPI.list() instead of scattering fetch everywhere. It's the
closest React analog to a controller: an object whose members are the functions that talk to
the server.
// src/staff/StaffAPI.ts
import { IStaff } from "./IStaff"; // ①
const url = "http://localhost:5556/api/staff"; // ②
export const staffAPI = { // ③ ④
list(): Promise<IStaff[]> { // ⑤ ⑥
return fetch(url).then((response) => response.json()); // ⑦ ⑧ ⑨ ⑩
},
};
| # | Token | What it is |
|---|---|---|
| ① | import { IStaff } … |
Named import — pulls IStaff in from its file (curly braces, exact name) |
| ② | url |
Constant — a const variable, set once and never reassigned |
| ③ | staffAPI |
Object — an object literal grouping related functions (your "API module") |
| ④ | list |
Method — a function stored as a property of that object |
| ⑤ | Promise<IStaff[]> |
Type argument (generic) — list returns a Promise of IStaff[]; the <…> fills in the generic |
| ⑥ | IStaff[] |
Array type — "an array of IStaff" |
| ⑦ | fetch(url) |
Function call — invoking the browser's built-in fetch |
| ⑧ | url (in fetch(url)) |
Argument — the actual value passed at the call site |
| ⑨ | .then(…) |
Method call — invoking then on the promise fetch returned |
| ⑩ | (response) => … |
Arrow function — an inline function; response is its parameter |
Specimen C — a list component (staff/StaffPage.tsx)¶
A function component is a function that returns JSX (the UI). This one holds the
fetched staff in state, loads them once on mount, and renders them with .map(). Trimmed
slightly (no loading flag or styling) to keep the callouts readable.
// src/staff/StaffPage.tsx
import { useEffect, useState } from "react"; // ①
import { IStaff } from "./IStaff";
import { staffAPI } from "./StaffAPI";
function StaffPage() { // ②
const [staff, setStaff] = useState<IStaff[]>([]); // ③ ④
async function loadStaff() { // ⑤
const data = await staffAPI.list(); // ⑥ ⑦
setStaff(data); // ⑧
}
useEffect(() => { // ⑨
loadStaff();
}, []);
return (
<section className="list">
{/* ⑩ = <section>, ⑪ = .map, ⑫ = staffMember */}
{staff.map((staffMember) => (
<div className="card" key={staffMember.id}>
{staffMember.firstName} {staffMember.lastName}
</div>
))}
</section>
);
}
export default StaffPage; // ⑬
| # | Token | What it is |
|---|---|---|
| ① | import { useEffect, useState } … |
Named import — brings the two hooks in from React |
| ② | StaffPage |
Function component — a function that returns JSX (React's unit of UI) |
| ③ | useState<IStaff[]>([]) |
Function call to a hook; [] is its argument (the initial value) |
| ④ | <IStaff[]> |
Type argument (generic) — tells useState the state holds an IStaff[] |
| ⑤ | loadStaff |
Function — a named function you define (here, nested inside the component) |
| ⑥ | data |
Local variable — a const that lives only inside loadStaff |
| ⑦ | staffAPI.list() |
Method call — invoking list on the staffAPI object |
| ⑧ | setStaff(data) |
Function call; data is the argument passed to the state setter |
| ⑨ | useEffect(() => {…}, []) |
Function call to a hook; its first argument is an arrow function |
| ⑩ | <section>…</section> |
JSX element — the UI this component returns (its one root element) |
| ⑪ | staff.map(…) |
Method call — invoking .map on the staff array |
| ⑫ | (staffMember) => … |
Arrow function; staffMember is its parameter (one item per element) |
| ⑬ | export default StaffPage |
Default export — the file's single main export (imported without braces) |
The distinctions students trip on¶
These pairs use similar words for different things. Getting them straight is the whole point of the exercise.
1. Interface vs. object. An interface (IStaff) is a compile-time blueprint — a
type that describes a shape and then disappears from the running code. An object
({ id: 1, firstName: "Sam", … }, or each item .json() hands back) is a real value living
in memory. You never write new IStaff(); you make plain objects that match the interface.
2. Local variable vs. state. Both hold data. A local variable (data in loadStaff)
is born inside a function and gone the instant it returns. State (staff from useState)
persists across renders and, when you change it with its setter (setStaff), tells React to
re-render. State is React's version of "a value the object keeps."
3. Type vs. value. IStaff is a type; staff is a value. Anything after a :
(: IStaff[]) or inside <…> (<IStaff[]>) is a type — checked at build time, then erased.
Everything else is a real value the program moves around. Casing can't tell them apart; only
position can.
4. Parameter vs. argument. A parameter is the placeholder in a function's
definition (staffMember in (staffMember) => …). An argument is the real value passed
at the call (data in setStaff(data)). Same idea, opposite ends of the call.
5. Function vs. function call. Defining loadStaff or StaffPage is a function.
Running staffAPI.list(), useState(...), or useEffect(...) is a call. A hook is
simply a function call whose name starts with use and that React treats specially.
6. Named vs. default export. export interface IStaff and import { IStaff } are
named — curly braces, exact name, a file can have many. export default StaffPage and
import StaffPage from … are default — no braces, one per file, and the importer may
rename it. Mixing them up ("why won't my import find it?") is the #1 import bug.
Bonus: primitive types vs. object types (the two kinds of type)¶
Every property, parameter, and variable has a type. Those types come in two families — and knowing which is which explains why the interface-vs-object distinction (#1) matters.
| Type in the specimens | Family | A variable of this type holds… |
|---|---|---|
number (id), string (firstName), boolean (isManager) |
primitive type — built-in, a lowercase keyword | the value itself, stored directly |
IStaff, IStaff[], { … } (an object literal) |
object type — interfaces, arrays, objects | a reference pointing to an object elsewhere in memory |
- Primitive types are the built-in simple kinds:
number,string,boolean(plusnullandundefined). Lowercase keywords. The variable is the value — copy it and you copy the number. - Object types are interfaces you define (
IStaff), arrays (IStaff[]), and object literals. The variable doesn't hold the object; it holds a reference to one. That's whystaff(the state) and the array it points to are two different things, and whystaff.map(...)reaches through the reference to the real array. - Two things that surprise C# developers: there's a single
number— no separateint/decimal/double. And TypeScript's types are structural and erased: it checks that an object has the right shape at build time, then throws the types away — the app that runs is plain JavaScript with noIStaffin sight.
A quick tell: primitive types are lowercase keywords (
number,string,boolean). Types in PascalCase (IStaff,Promise) are ones with a name you could go read — an interface, class, or built-in object type.
How to use this in a lesson¶
- As a warm-up quiz: hand out the blank version — same code, empty legend, a word bank — and have students fill it in before revealing this key.
- As a live callout: during the Lesson 3–4 build, pause on each new token and ask "interface, object, function, call, parameter, or hook?" before moving on.
- In the capstone: the exact same parts appear in
UserAPI.tsand every other PRS feature (ProductsPage,VendorAPI, …). The vocabulary transfers unchanged — open your own file and name each part; if a token stumps you, that's the thing to go look up.