Lessons in this course (9)

9. Typing real API calls in Angular and React

Advanced★ Must knowLesson 9 of 9
typescript
// models.ts — generated from the backend OpenAPI or written by hand
export interface OrderDto { id: number; orderDate: string; status: OrderStatus; total: number; }

// Angular service
@Injectable({ providedIn: "root" })
export class OrdersApi {
  private http = inject(HttpClient);
  list(page: number) { return this.http.get<Paged<OrderDto>>("/api/orders", { params: { page } }); }
}

// React with fetch + runtime validation (types alone don't check the server response)
import { z } from "zod";
const OrderSchema = z.object({ id: z.number(), orderDate: z.string(), status: z.enum(["draft", "submitted", "shipped"]), total: z.number() });
type Order = z.infer<typeof OrderSchema>;

async function getOrders(): Promise<Order[]> {
  const res = await fetch("/api/orders");
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return z.array(OrderSchema).parse(await res.json());   // throws if the API shape changed
}

// Typed React props and state
type Props = { orders: Order[]; onSelect: (id: number) => void };
function OrderTable({ orders, onSelect }: Props) { /* … */ }
const [selected, setSelected] = useState<Order | null>(null);

Interview tip: http.get<T>() and as T are promises to the compiler, not checks. Mention generating types from OpenAPI and validating at the boundary.